/*
 * Copyright 2007-2009 Perttu "celeron55" Ahola <celeron55@gmail.com>
 *
 * This file is part of jukuMagic.
 *
 * jukuMagic is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * jukuMagic is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with jukuMagic.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "board.h"
#include "commonfunctions.h"
#include <assert.h>
#include <algorithm>
#include <stdio.h>

#define WIRE_ALLOW_BLOCKED false
#define DISABLE_OPTIMIZATIONS false
#define CLEANEVERYTHING_LOOPCOUNT_MAX 3
//#define MAX_ADDITIONAL_X_SPACING 3
//#define MAX_ADDITIONAL_X_SPACING 8
#define MAX_ADDITIONAL_X_SPACING 2
#define DISABLE_PARTPLACE_BRUTEFORCE true
#define CONNECTION_SCORE_ONLY_MEASURE_CLOSEST_FEET false
#define DO_STRAIGHTEN_EVERY_TIME false

Board::Board()
{
	width=0;
	height=0;
	circuitp = NULL;
	InformContentChanged();
}

int Board::BFindPartNumWithFootNum(int num)
{
	for(unsigned int i=0; i<parts.size(); i++){
		if(parts[i].GetFootprint()->GetFootByNumber(num).number != -1) return i;
	}
	return -1;
}

int Board::BFindWirePartNumWithFootNum(int num)
{
	//cout<<"Circuit::FindWirePartNumWithFootNum("<<num<<")"<<endl;
	//cout<<"We have "<<wireparts.size()<<" wireparts"<<endl;
	for(unsigned int i=0; i<wparts.size(); i++){
		//cout<<"Part "<<i<<" is named "<<wireparts[i].Name()
				//<<" and has footnums "<<wireparts[i].FootNum1()
				//<<" and "<<wireparts[i].FootNum2()<<endl;
		if(wparts[i].FootNum1() == num) return i;
		if(wparts[i].FootNum2() == num) return i;
	}
	return -1;
}

int Board::BFindWireNumWithFootNum(int num)
{
	//cout<<"Circuit::FindWireNumWithFootNum("<<num<<")"<<endl;
	//cout<<"We have "<<wires.size()<<" wires"<<endl;
	for(unsigned int i=0; i<wires.size(); i++){
		//cout<<"Part "<<i<<" is named "<<wires[i].Name()
				//<<" and has footnums "<<wires[i].FootNum1()
				//<<" and "<<wires[i].FootNum2()<<endl;
		if(wires[i].num == num) return i;
	}
	return -1;
}

/*bool Board::AddToNFClist(int num)
{
	if(!IsOnNFClist(num)){
		footnums_as_nfc.push_back(num);
		return true;
	}
	return false;
}

bool Board::IsOnNFClist(int num)
{
	for(unsigned int i=0; i<footnums_as_nfc.size(); i++){
		if(num == footnums_as_nfc[i]) return true;
	}
	return false;
}*/

int Board::GetPartNFCleft(Part &part, unsigned int y)
{
	//cout<<"Circuit::GetPartNFCleft()"<<endl;
	vector< vector<Contentblock> > cblocks = part.GetFootprint()->Contentblocks();
	unsigned int h = cblocks.size();
	if(h==0) return -1;
	unsigned int w = cblocks[0].size();
	if(y >= h){
		cout<<"GetPartNFCleft: ERROR: too high y"<<endl;
		return -1;
	}
	int snleft=0; //space needed
	for(unsigned int x=0; x<w; x++){
		if(cblocks[y][x].type == PFOOT){
			vector<int> footnums = circuitp->GetFootNumsConnected(cblocks[y][x].num);
			/*unsigned int cons = 0;
			//lisätään listalla olemattomat jalat listalle ja samalla kasvatetaan cons-muuttujaa
			for(unsigned int i=0; i<footnums.size(); i++){
				cons += IsOnNFClist(footnums[i]) == false ? 1 : 0;
			}*/
			unsigned int cons = footnums.size();
			//cout<<"GetPartNFCleft: cons = "<<cons<<endl;
			snleft = cons /*- x*/;
			break;
		}
	}
	if(snleft < 0){
		cout<<"GetPartNFCleft: WARNING: snleft < 0"<<endl;
		snleft = 0;
	}
	if(snleft==0) snleft = 1;
	if(snleft>1 && part.GetFootprint()->HasAdjacentFeet()) snleft /= 2;
	//if(snleft>4) snleft = 4;
	return snleft;
}
int Board::GetPartNFCright(Part &part, unsigned int y)
{
	//cout<<"Circuit::GetPartNFCright()"<<endl;
	vector< vector<Contentblock> > cblocks = part.GetFootprint()->Contentblocks();
	unsigned int h = cblocks.size();
	if(h==0){
		cout<<"GetPartNFCright: ERROR: part has zero height"<<endl;
		return -1;
	}
	unsigned int w = cblocks[0].size();
	if(y > h){
		cout<<"GetPartNFCright: ERROR: too high y"<<endl;
		return -1;
	}
	int snright=0; //space needed
	for(int x=w-1; x>=0; x--){
		if(cblocks[y][x].type == PFOOT){
			vector<int> footnums = circuitp->GetFootNumsConnected(cblocks[y][x].num);
			/*unsigned int cons = 0;
			//lisätään listalla olemattomat jalat listalle ja samalla kasvatetaan cons-muuttujaa
			for(unsigned int i=0; i<footnums.size(); i++){
				cons += IsOnNFClist(footnums[i]) == false ? 1 : 0;
			}*/
			unsigned int cons = footnums.size();
			//cout<<"GetPartNFCright: cons = "<<cons<<endl;
			/*if(snright < 0){
				cout<<"GetPartNFCright: WARNING: snright < 0"<<endl;
				snright = 0;
			}*/
			snright = cons /*- (w-1-x)*/;
			break;
		}
	}
	//snright = cons - (w-1-x);
	if(snright < 0){
		cout<<"GetPartNFCright: WARNING: snright < 0"<<endl;
		snright = 0;
	}
	if(snright==0) snright = 1;
	if(snright>1 && part.GetFootprint()->HasAdjacentFeet()) snright /= 2;
	//if(snright>4) snright = 4;
	return snright;
}

/*
Coord Board::GetApproxBoardCentre()
{
	//tutkitaan paljonko tyhjää on ylhäällä
	unsigned int xstartoffset = 0;
	for(unsigned int y=0; y<height; y++){
		bool somethingfound = false;
		for(unsigned int x=0; x<width; x++){
			if(Content(x, y).type!=CUT){
				somethingfound = true;
				break;
			}
		}
		if(somethingfound){
			xstartoffset = y;
			break;
		}
	}
	//tutkitaan paljonko tyhjää on vasemmalla
	unsigned int ystartoffset = 0;
	for(unsigned int x=0; x<width; x++){
		bool somethingfound = false;
		for(unsigned int y=0; y<height; y++){
			if(Content(x, y).type!=CUT){
				somethingfound = true;
				break;
			}
		}
		if(somethingfound){
			ystartoffset = x;
			break;
		}
	}
	//tutkitaan paljonko tyhjää on oikealla
	unsigned int xendoffset = 0;
	for(unsigned int x=width-1; x>0; x--){
		bool somethingfound = false;
		for(unsigned int y=0; y<height; y++){
			if(Content(x, y).type != CUT && Content(x, y).type != HOLE){
				somethingfound = true;
				break;
			}
		}
		if(somethingfound){
			xendoffset = x+1;
			break;
		}
	}
	//tutkitaan paljonko tyhjää on alhaalla
	unsigned int yendoffset = 0;
	for(unsigned int y=height-1; y>0; y--){
		bool somethingfound = false;
		for(unsigned int x=0; x<width; x++){
			if(Content(x, y).type != CUT && Content(x, y).type != HOLE){
				somethingfound = true;
				break;
			}
		}
		if(somethingfound){
			yendoffset = y+1;
			break;
		}
	}
	cout<<"xstartoffset="<<xstartoffset<<", ystartoffset="<<ystartoffset
			<<", xendoffset="<<xendoffset<<", yendoffset="<<yendoffset<<endl;
	if(xendoffset < xstartoffset || yendoffset < ystartoffset){
		cout<<"Board::GetApproxBoardCentre(): empty board! returning (0,0)"<<endl;
		return MakeCoord(0,0);
	}
	unsigned int realwidth = xendoffset - xstartoffset;
	unsigned int realheight = yendoffset - ystartoffset;
	Coord centrec = MakeCoord(realwidth/2 + xstartoffset, realheight/2 + ystartoffset);
	cout<<"centrec = ("<<centrec.x<<","<<centrec.y<<")"<<endl;
	return centrec;
}
*/

bool Board::IsFreePlace(unsigned int x, unsigned int y, unsigned int w, unsigned int h, unsigned int freexspace)
{
	if(x<0 || x+w>width || y<0 || y+h>height){
		cout<<"Board::IsFreePlace: invalid coords: "<<x<<","<<y<<endl;
		return false;
	}
	//cout<<"isfreeplace testing"<<endl;
	for(unsigned int y0 = 0; y0 < h; y0++){
		int y1 = y + y0;
		//cout<<"y = "<<y1<<", ";
		for(int x0 = -freexspace; x0 < (int)(w + freexspace); x0++){
			int x1 = x + x0;
			Contentblock b = Content(x1, y1);
			//cout<<"\tx="<<x1<<":"<<b.type<<";";
			if((b.type != CUT && b.type != OVERBOARD) || b.partname_blocks != ""){
				//cout<<" FAIL"<<endl;
				return false;
			}
		}
		//cout<<endl;
	}
	//cout<<"SUCCEED"<<endl;
	return true;
}

Coord Board::FindFreePlace(unsigned int w, unsigned int h, unsigned int freexspace)
{
	//cout<<"Finding place sized "<<w<<"x"<<h<<" with freexspace="<<freexspace<<endl;
	Coord c;
	if(height - h < 0 || width - w < 0){
		cout<<"Component too big"<<endl;
		return MakeInexistentCoord();
	}
	for(unsigned int y=0; y+h<height+1; y++){
		for(unsigned int x=freexspace-1; x+freexspace+w<width+1; x++){
			//cout<<"Testing place x="<<x<<" y="<<y<<endl;
			if(IsFreePlace(x, y, w, h, freexspace)){
				c.x = x;
				c.y = y;
				return c;
			}
		}
	}
	c.exist = false;
	return c;
}

Coord Board::FindClosestPossibleFreePlace(vector<Coord> &fromcs, unsigned int w, unsigned int h,
		unsigned int freexspace)
{
	//cout<<"Finding closest possible place sized "<<w<<"x"<<h<<" with freexspace="<<freexspace<<endl;
	if(height - h < 0 || width - w < 0){
		cout<<"Board::FindClosestPossibleFreePlace(): ERROR: Component too big"<<endl;
		return MakeInexistentCoord();
	}
	double mindistance = 0;
	Coord minc = MakeInexistentCoord();
	for(unsigned int y=0; y+h<height+1; y++){
		for(unsigned int x=freexspace; x+freexspace+w<width+1; x++){
			//cout<<"Testing place x="<<x<<" y="<<y<<endl;
			if(IsFreePlace(x, y, w, h, freexspace)){
				double distance = Distance(MakeCoord(x+w/2, y), fromcs);
				//cout<<"found free place from "<<x<<","<<y<<". distance = "<<distance<<endl;
				if(!minc.exist || distance < mindistance){
					minc = MakeCoord(x, y);
					mindistance = distance;
				}
			}
		}
	}
	/*cout<<"from: ";
	for(unsigned int i=0; i<fromcs.size(); i++){
		cout<<"("<<fromcs[i].x<<","<<fromcs[i].y<<"), ";
	}
	cout<<endl<<"minimum distance is "<<mindistance<<", coords="<<minc.x<<","<<minc.y<<endl;*/
	return minc;
}

Coord Board::FindClosestPossibleFreePlace(Coord fromc, unsigned int w, unsigned int h,
		unsigned int freexspace)
{
	vector<Coord> fromcs;
	fromcs.push_back(fromc);
	return FindClosestPossibleFreePlace(fromcs, w, h, freexspace);
}

/*Coord Board::FindClosestPossibleFreePlace(vector<Coord> &fromcs, unsigned int w, unsigned int h,
		unsigned int freexspace)
{
	vector<Coord> notdcs;
	return FindClosestPossibleFreePlace(fromcs, w, h, freexspace, notdcs);
}

Coord Board::FindClosestPossibleFreePlace(Coord fromc, unsigned int w, unsigned int h,
		unsigned int freexspace)
{
	vector<Coord> fromcs;
	vector<Coord> notdcs;
	fromcs.push_back(fromc);
	return FindClosestPossibleFreePlace(fromcs, w, h, freexspace, notdcs);
}*/

Coord Board::FindFreePlaceWithMaxRoom(unsigned int w, unsigned int h)
{
	//cout<<"Finding place sized "<<w<<"x"<<h<<" with maximum room"<<endl;
	Coord c = MakeInexistentCoord(), lastc;
	int lasti = 0;
	for(unsigned int i=0; ; i++){
		lastc = c;
		if(!(c = FindFreePlace(w+i, h+i, 3)).exist){
			lastc.x += lasti;
			lastc.y += lasti;
			break;
		}
		lasti = i;
	}
	
	return lastc;
}

bool Board::IsRouteClear(Coord c1, Coord c2)
{
	vector<Coord> cs;
	Line(c1.x, c1.y, c2.x, c2.y, cs);
	for(unsigned int i=0; i<cs.size(); i++){
		if(Content(cs[i]).partname_blocks != ""){
			return false;
		}
	}
	return true;
}

bool Board::IsFreePlaceForPart(Part &part, unsigned int x, unsigned int y, int losen)
{
	//cout<<"Board::IsFreePlaceForPart(part, x="<<x<<", y="<<y<<")"<<endl;
	unsigned int w = part.GetFootprint()->Width();
	unsigned int h = part.GetFootprint()->Height();
	//cout<<"part width="<<w<<" height="<<h<<endl;
	if(x<0 || x+w>width || y<0 || y+h>height){
		cout<<"Board::IsFreePlaceForPart: invalid coords (part outside of area): "
				<<x<<","<<y<<endl;
		return false;
	}
	//cout<<"IsFreePlaceForPart: testing ("<<x<<","<<y<<")"<<endl;
	for(unsigned int y0 = 0; y0 < h; y0++){
		int y1 = y + y0;
		//cout<<"y on part: "<<y0<<", on board: "<<y1<<endl;
		int nfcleft  = GetPartNFCleft(part, y0);
		if(nfcleft == -1){
			cout<<"Board::IsFreePlaceForPart: ERROR: nfcleft==-1"<<endl;
			return false;
		}
		int nfcright = GetPartNFCright(part, y0);
		if(nfcright == -1){
			cout<<"Board::IsFreePlaceForPart: ERROR: nfcright==-1"<<endl;
			return false;
		}
		//cout<<"nfcleft="<<nfcleft<<", nfcright="<<nfcright<<endl;
		/*
		//TODO: lulz
		if(losen > nfcleft + additional_x_spacing) return false;
		if(losen > nfcright + additional_x_spacing) return false;
		*/
		int relstartx = x - nfcleft - additional_x_spacing + losen;
		int relendx = x + w + nfcright + additional_x_spacing - losen;
		//cout<<"checking from x="<<relstartx<<" to x="<<relendx<<endl;
		if(part.GetFootprint()->HasAdjacentFeet()){
			if(relstartx < 0){
				//cout<<"Board::IsFreePlaceForPart: over left border"<<endl;
				return false;
			}
			if(relendx >= (int)width){
				//cout<<"Board::IsFreePlaceForPart: over right border"<<endl;
				return false;
			}
			for(int x1 = relstartx; x1 <= relendx; x1++){
				//cout<<"checking ("<<x1<<","<<y1<<")"<<endl;
				if(Content(x1,y1).type != CUT){
					/*cout<<"Board::IsFreePlaceForPart: ("<<x1<<","<<y1<<
							") type not CUT"<<endl;*/
					return false;
				}
				if(Content(x1,y1).nfc_partnum >= 0){
					/*cout<<"Board::IsFreePlaceForPart: ("<<x1<<","<<y1<<
							") needed for connection"<<endl;*/
					return false;
				}
			}
		}
		else{
			//cout<<"Board::IsFreePlaceForPart(): "<<part.Name()<<" has no adjacent feet"<<endl;
			if(x < 0 || y + w >= width || w + nfcleft > width){
				//cout<<"Board::IsFreePlaceForPart: over border"<<endl;
				return false;
			}
			//TODO: lölz
			/*
			relendx -= (nfcright + additional_x_spacing - losen);
			if(relstartx < 0){
				relendx -= relstartx;
				relstartx = 0;
			}*/
			//cout<<"Board::IsFreePlaceForPart(): relstartx="<<relstartx<<" relendx="<<relendx<<endl;
			for(int x1 = relstartx; x1 <= relendx; x1++){
				//cout<<"checking ("<<x1<<","<<y1<<")"<<endl;
				if(Content(x1,y1).type != CUT){
					/*cout<<"Board::IsFreePlaceForPart: ("<<x1<<","<<y1<<
							") type not CUT"<<endl;*/
					return false;
				}
				if(Content(x1,y1).nfc_partnum >= 0){
					/*cout<<"Board::IsFreePlaceForPart: ("<<x1<<","<<y1<<
							") needed for connection"<<endl;*/
					return false;
				}
			}
		}
	}
	//cout<<"IsFreePlaceForPart: ("<<x<<","<<y<<") is free."<<endl;
	return true;
}

Coord Board::FindFreePlaceForPart(Part &part)
{
	//if(debugmessages_on) cout<<"Board::FindFreePlaceForPart()"<<endl;
	unsigned int w = part.GetFootprint()->Width();
	unsigned int h = part.GetFootprint()->Height();
	Coord c = MakeInexistentCoord();
	if(height - h < 0 || width - w < 0){
		cout<<"Board::FindFreePlaceForPart(): ERROR: part too big"<<endl;
		return MakeInexistentCoord();
	}
	int maxnfcleft=0, maxnfcright=0;
	for(unsigned int y0 = 0; y0 < h; y0++){
		//cout<<"y on part: "<<y0<<", on board: "<<y1<<endl;
		int nfcleft  = GetPartNFCleft(part, y0);
		assert(nfcleft>=0);
		int nfcright = GetPartNFCright(part, y0);
		assert(nfcright>=0);
		if(nfcleft > maxnfcleft) maxnfcleft = nfcleft;
		if(nfcright > maxnfcright) maxnfcright = nfcright;
	}
	/*if(debugmessages_on)
		cout<<"Board::FindFreePlaceForPart(): part size="<<w<<"x"<<h<<", maxnfcleft="
				<<maxnfcleft<<", maxnfcright="<<maxnfcright<<endl;*/
	/*if(w + maxnfcleft + maxnfcright + additional_x_spacing*2 > width){
		cout<<"Board::FindFreePlaceForPart(): ERROR: part + nfcs too big"<<endl;
		return MakeInexistentCoord();
	}*/
	/*if(debugmessages_on)
		cout<<"Board::FindFreePlaceForPart(): testing places: ";*/
	
	//TODO: tämä losen-systeemi nyt ainakin on ihan perseestä, kuten tuo additional_x_spacing ja myöskin needed_for_connection-jutut
	
	int losen = 0;
	//for(int losen = 0; losen < additional_x_spacing + maxnfcleft+maxnfcright; losen++){
		//if(debugmessages_on) cout<<"losen="<<losen<<endl;
		for(unsigned int y=0; y+h<height+1; y++){
			/*for(unsigned int x = maxnfcleft + additional_x_spacing;
					x + w + maxnfcright + additional_x_spacing < width+1; x++){*/
			for(unsigned int x = 0; x + w < width+1; x++){
				//if(debugmessages_on) cout<<"("<<x<<","<<y<<") ";
				if(IsFreePlaceForPart(part, x, y, losen)){
					c.x = x;
					c.y = y;
					c.exist = true;
					//if(debugmessages_on) cout<<endl;
					//cout<<"Board::FindFreePlaceForPart: Found at ("<<c.x<<","<<c.y<<")"<<endl;
					return c;
				}
			}
		}
	//}
	
	if(!c.exist){
		cout<<"Board::FindFreePlaceForPart(): couldn't find free place for part \""<<part.Name()<<"\""<<endl;
		for(unsigned int y=0; y<part.GetFootprint()->Height(); y++){
			cout<<"y="<<y<<": nfcleft="<<GetPartNFCleft(part, y)<<" nfcright="<<GetPartNFCright(part, y)<<endl;
		}
		cout<<"board nfc's:"<<endl;
		for(unsigned int y=0; y<height; y++){
			for(unsigned int x=0; x<width; x++){
				if(Content(x,y).nfc_partnum != -1) cout<<" Y";
				else cout<<" N";
			}
			cout<<endl;
		}
	}

	/*if(debugmessages_on)
		cout<<endl<<"Board::FindFreePlaceForPart: Didn't find"<<endl;*/
	//c.exist = false;
	return c;
}

vector<Coord> Board::FindAllFreePlacesForPart(Part &part)
{
	cout<<"Board::FindAllFreePlacesForPart()"<<endl;
	unsigned int w = part.GetFootprint()->Width();
	unsigned int h = part.GetFootprint()->Height();
	Coord c;
	vector<Coord> foundcoords;
	if(height - h < 0 || width - w < 0){
		cout<<"Board::FindAllFreePlacesForPart(): ERROR: part too big"<<endl;
		return foundcoords;
	}
	for(unsigned int y=0; y+h<height+1; y++){
		for(unsigned int x=0; x+w<width+1; x++){
			//cout<<"Testing place x="<<x<<" y="<<y<<endl;
			if(IsFreePlaceForPart(part, x, y, 0)){
				c.x = x;
				c.y = y;
				foundcoords.push_back(c);
				//cout<<"Board::FindAllFreePlacesForPart: Found at ("<<c.x<<","<<c.y<<")"<<endl;
			}
		}
	}
	if(foundcoords.empty()){
		cout<<"Board::FindAllFreePlacesForPart(): couldn't find free place for part \""<<part.Name()<<"\""<<endl;
		for(unsigned int y=0; y<part.GetFootprint()->Height(); y++){
			cout<<"y="<<y<<": nfcleft="<<GetPartNFCleft(part, y)<<" nfcright="<<GetPartNFCright(part, y)<<endl;
		}
		cout<<"board nfc's:"<<endl;
		for(unsigned int y=0; y<height; y++){
			for(unsigned int x=0; x<width; x++){
				if(Content(x,y).nfc_partnum != -1) cout<<" Y";
				else cout<<" N";
			}
			cout<<endl;
		}
	}
	return foundcoords;
}

Coord Board::FindClosestPossibleFreePlaceForPart(Coord fromc, Part &part)
{
	assert(0);
	//TODO: älykkäämpi systeemi
	cout<<"Board::FindClosestPossibleFreePlaceForPart()"<<endl;
	unsigned int w = part.GetFootprint()->Width();
	unsigned int h = part.GetFootprint()->Height();
	double mindistance = 0;
	Coord minc = MakeInexistentCoord();
	vector<Coord> places = FindAllFreePlacesForPart(part);
	for(unsigned int i=0; i<places.size(); i++){
		double distance = Distance(places[i] + MakeCoord(w/2,h/2), fromc);
		if(!minc.exist || distance < mindistance){
			cout<<"distance went down; is now"<<distance<<endl;
			minc = places[i];
			mindistance = distance;
		}
	}
	//cout<<"minimum distance is "<<mindistance<<", coords="<<minc.x<<","<<minc.y<<endl;
	return minc;
}

Coord Board::FindClosestPossibleFreePlaceForPart(vector<Coord> fromcs, Part &part)
{
	assert(0);
	cout<<"Board::FindClosestPossibleFreePlaceForPart() (many fromcs)"<<endl;
	unsigned int w = part.GetFootprint()->Width();
	unsigned int h = part.GetFootprint()->Height();
	double mindistance = 0;
	Coord minc = MakeInexistentCoord();
	vector<Coord> places = FindAllFreePlacesForPart(part);
	for(unsigned int i=0; i<places.size(); i++){
		double distance = Distance(places[i] + MakeCoord(w/2,h/2), fromcs);
		if(!minc.exist || distance < mindistance){
			//cout<<"distance went down; is now "<<distance<<endl;
			minc = places[i];
			mindistance = distance;
		}
	}
	//cout<<"minimum distance is "<<mindistance<<", coords="<<minc.x<<","<<minc.y<<endl;
	return minc;
}

Coord Board::FindHighestScoredFreePlaceForPart(Part &part)
{
	//if(debugmessages_on) cout<<"Board::FindHighestScoredFreePlaceForPart(name="<<part.Name()<<")"<<endl;
	double bestscore = 0;
	Coord c = MakeInexistentCoord();
	vector<Coord> places = FindAllFreePlacesForPart(part);
	for(unsigned int i=0; i<places.size(); i++){
		double score = ConnectionScore(part, places[i]);
		//if(debugmessages_on) cout<<places[i].String()<<": score="<<score<<endl;
		if(!c.exist || score > bestscore){
			bestscore = score;
			c = places[i];
		}
	}
	//if(debugmessages_on) cout<<"bestscore="<<bestscore<<" @ "<<c.String()<<endl;
	return c;
}

bool Board::PutPart(Part &part)
{
	//cout<<"ADDING PART"<<endl;
	if(!part.GetCoord().exist){
		cout<<"Board::PutPart: coords inexistent"<<endl;
		return false;
	}
	if(circuitp == NULL){
		cout<<"Board::PutPart: ERROR: circuitp NULL"<<endl;
		return false;
	}
	unsigned int x = part.GetCoord().x;
	unsigned int y = part.GetCoord().y;
	vector< vector<Contentblock> > cblocks = part.GetFootprint()->Contentblocks();
	unsigned int h = cblocks.size();
	unsigned int w = cblocks[0].size();
	if(Width() > x+w-1 && Height() > y+h-1 && x >= 0 && y >= 0){
		parts.push_back(part);
		InformContentChanged();
		vector<Foot> foots = part.GetFootprint()->Foots();
		/*for(unsigned int i=0; i<foots.size(); i++){
			AddToNFClist(foots[i].number);
		}*/
		//
		for(unsigned int y=0; y<part.GetFootprint()->Height(); y++){
			cout<<"y="<<y<<": nfcleft="<<GetPartNFCleft(part, y)<<" nfcright="<<GetPartNFCright(part, y)<<endl;
		}
		cout<<"board nfc's:"<<endl;
		for(unsigned int y=0; y<height; y++){
			for(unsigned int x=0; x<width; x++){
				if(Content(x,y).nfc_partnum != -1) cout<<" Y";
				else cout<<" N";
			}
			cout<<endl;
		}
		//
		return true;
	}
	cout<<"Board::PutPart: Can't put here"<<endl;
	return false;
}

bool Board::PutPartSomewhere(Part &part)
{
	//cout<<"Adding part "<<part.Name()<<" somewhere"<<endl;
	/*Coord newpartcoords = FindFreePlace(part.GetFootprint()->Width(),
			part.GetFootprint()->Height(), xspacing);*/
	Coord newpartcoords = FindFreePlaceForPart(part);
	if(!newpartcoords.exist){
		if(debugmessages_on) cout<<"Could not find coords for part named "<<part.Name()<<endl;
		return false;
	}
	part.SetCoord(newpartcoords);
	//cout<<"coords "<<part.GetCoord().x<<","<<part.GetCoord().y<<endl;
	bool ret = PutPart(part);
	if(ret==false){
		cout<<"Board::PutPartSomewhere(): PutPart error\n"<<endl;
	}
	return ret;
}

bool Board::PutPartSomewhereNear(Part &part, Coord fromc)
{
	//cout<<"Adding part "<<part.Name()<<" somewhere"<<endl;
	/*Coord newpartcoords = FindClosestPossibleFreePlace(fromc,
			part.GetFootprint()->Width(), part.GetFootprint()->Height(), xspacing);*/
	Coord newpartcoords = FindClosestPossibleFreePlaceForPart(fromc, part);
	if(!newpartcoords.exist){
		//cout<<"Could not find coords for part named "<<part.Name()<<endl;
		return false;
	}
	part.SetCoord(newpartcoords);
	//cout<<"coords "<<part.GetCoord().x<<","<<part.GetCoord().y<<endl;
	return PutPart(part);
}

bool Board::PutPartSomewhereNear(Part &part, vector<Coord> fromcs)
{
	//cout<<"Adding part "<<part.Name()<<" somewhere"<<endl;
	/*Coord newpartcoords = FindClosestPossibleFreePlace(fromc,
			part.GetFootprint()->Width(), part.GetFootprint()->Height(), xspacing);*/
	Coord newpartcoords = FindClosestPossibleFreePlaceForPart(fromcs, part);
	if(!newpartcoords.exist){
		//cout<<"Could not find coords for part named "<<part.Name()<<endl;
		return false;
	}
	part.SetCoord(newpartcoords);
	//cout<<"coords "<<part.GetCoord().x<<","<<part.GetCoord().y<<endl;
	return PutPart(part);
}

bool Board::PutPartSomewhereWithMaxRoom(Part &part)
{
	//cout<<"Adding part "<<part.Name()<<" somewhere with max room"<<endl;
	Coord newpartcoords = FindFreePlaceWithMaxRoom(part.GetFootprint()->Width(),
			part.GetFootprint()->Height());
	if(!newpartcoords.exist){
		//cout<<"Could not find coords for part named "<<part.Name()<<endl;
		return false;
	}
	part.SetCoord(newpartcoords);
	//cout<<"coords "<<part.GetCoord().x<<","<<part.GetCoord().y<<endl;
	return PutPart(part);
}

bool Board::PutPartToBestScoredPlace(Part &part)
{
	if(DISABLE_PARTPLACE_BRUTEFORCE){
		return PutPartSomewhere(part);
	}
	Coord newpartcoords = FindHighestScoredFreePlaceForPart(part);
	part.GetFootprint()->SetRotate(true);
	Coord newpartcoords_rotated = FindHighestScoredFreePlaceForPart(part);
	if(!newpartcoords.exist && !newpartcoords_rotated.exist){
		cout<<"Board::PutPartToBestScoredPlace(): name="<<part.Name()<<": no place"<<endl;
		return false;
	}
	else if(!newpartcoords.exist){
		part.SetCoord(newpartcoords);
	}
	else if(!newpartcoords_rotated.exist){
		part.GetFootprint()->SetRotate(false);
		part.SetCoord(newpartcoords);
	}
	else{
		if(ConnectionScore(part, newpartcoords) >= ConnectionScore(part, newpartcoords_rotated)){
			part.GetFootprint()->SetRotate(false);
			part.SetCoord(newpartcoords);
		}
		else{
			part.SetCoord(newpartcoords_rotated);
		}
	}
	return PutPart(part);
}

bool Board::PutWirePart(WirePart wp)
{
	//cout<<"ADDING WIREPART"<<endl;
	int num = BFindWirePartNumWithFootNum(wp.FootNum1());
	if(num != -1){
		cout<<"Board::PutWirePart(): FATAL: putting WirePart that is already on board"<<endl;
		return false;
	}
	unsigned int x1 = wp.C1().x;
	unsigned int y1 = wp.C1().y;
	unsigned int x2 = wp.C2().x;
	unsigned int y2 = wp.C2().y;
	//tänne ei pitäisi tulla enää muute kuin half-defineddejä
	assert(!(wp.C1().exist && wp.C2().exist));
	if(wp.C1().exist && wp.C2().exist){
		/*if((Content(x1,y1).type == HOLE || Content(x1,y1).type == CUT) &&
				(Content(x2,y2).type == HOLE || Content(x2,y2).type == CUT)){
			wparts.push_back(wp);
			InformContentChanged();
			return true;
		}*/
		return false;
	}
	else if(wp.C1().exist){
		cout<<"Board::PutWirePart(): adding half-defined WirePart with head 1"<<endl;
		if(Content(x1,y1).type == HOLE || Content(x1,y1).type == CUT){
			wparts.push_back(wp);
			InformContentChanged();
			return true;
		}
	}
	else if(wp.C2().exist){
		cout<<"Board::PutWirePart(): adding half-defined WirePart with head 2"<<endl;
		if(Content(x2,y2).type == HOLE || Content(x2,y2).type == CUT){
			wparts.push_back(wp);
			InformContentChanged();
			return true;
		}
	}
	cout<<"Board::PutWirePart: Can't put here: @head1:("<<x1<<","<<y1<<")="<<Content(x1,y1).type<<", @head2:("<<x2<<","<<y2<<")="<<Content(x2,y2).type<<endl;
	return false;
}

bool Board::PutWirePartWisely(WirePart wp, unsigned int partxspacing)
{
	cout<<"Board::PutWirePartWisely()"<<endl;
	//tarkista pituus ja vedä hyppylanka lisäksi jos tarvii
	//double distance = Distance(wp.C1(), wp.C2());
	//ei tähän kai enää pitäisi tulla koskaan wirepartteja kokonaan määriteltynä?
	assert(wp.HalfDefined());
	if(wp.HalfDefined()){
		cout<<"half-defined wirepart: putting"<<endl;
		return PutWirePart(wp);
	}
	return false;
#if 0
	else if(distance > (double)wp.Length()){
		cout<<"Too long distance for this wirepart: "<<distance<<" > "<<wp.Length()<<endl;
putwirepartwithwire:
		//etsi lähin paikka johon pää mahtuu
		Coord oldc2 = wp.C2();
		Coord newc2 = FindClosestPossibleFreePlace(wp.C1(), 1, 1, partxspacing);
		if(!newc2.exist){
			cout<<"Could not get free place"<<endl;
			return false;
		}
		double newdistance = Distance(wp.C1(), newc2);
		cout<<"old="<<distance<<" new="<<newdistance<<endl;
		if(newdistance > (double)wp.Length()){
			cout<<"Couldn't make it short enough"<<endl;
			return false;
		}
		//tunge wirepart siihen
		cout<<"old coords: "<<wp.C1().x<<","<<wp.C1().y<<" "<<wp.C2().x<<","<<wp.C2().y<<endl;
		wp.SetCoord(wp.C1(), newc2);
		cout<<"new coords: "<<wp.C1().x<<","<<wp.C1().y<<" "<<wp.C2().x<<","<<wp.C2().y<<endl;
		if(!PutWirePart(wp)){
			cout<<"Could not put wirepart"<<endl;
			return false;
		}
		cout<<"Connecting from "<<newc2.x<<","<<newc2.y<<" to "<<oldc2.x<<","<<oldc2.y<<endl;
		//tunge johto
		if(!ConnectCoord(newc2, oldc2)){
			cout<<"Could not connect WirePart head to destination"<<endl;
			cout<<"Deleting WirePart."<<endl;
			int num = BFindWirePartNumWithFootNum(wp.FootNum1());
			if(num==-1){
				cout<<"Fatal error!"<<endl;
				return false;
			}
			wparts.erase(wparts.begin()+num);
			return false;
		}
		cout<<"Board::PutWirePartWisely(): now connected"<<endl;
		return true;
	}
	else{
		if(IsRouteClear(wp.C1(), wp.C2())){
			cout<<"distance short enough ("<<distance<<") and route is clear"<<endl;
			return PutWirePart(wp);
		}
		else{
			cout<<"distance short enough ("<<distance<<") but route isn't clear"<<endl;
			//TODO: vähän ehkä hienostuneemmin?
			goto putwirepartwithwire;
		}
	}
#endif
}

bool Board::PutWire(Wire wire)
{
	//TODO: pitäisi ehkä tarkistaa että paikassa on jotain järkeä
	//TODO: entä wirenumcounter? pitäisiköhän olla täällä (ConnectCoordin asia nyt,
	//ainoa tämän käyttäjä)
	wires.push_back(wire);
	InformContentChanged();
	return true;
}

bool Board::MoveWirePartHead(unsigned int wpnum, Coord c_from, Coord c_to)
{
	//cout<<"Moving WirePart "<<wpnum<<" from "<<c_from.x<<","<<c_from.y<<" to "<<c_to.x<<","<<c_to.y<<endl;
	if(wparts[wpnum].C1() == c_from){
		wparts[wpnum].SetCoord(c_to, wparts[wpnum].C2());
	}
	else if(wparts[wpnum].C2() == c_from){
		wparts[wpnum].SetCoord(wparts[wpnum].C1(), c_to);
	}
	else{
		cout<<"Board::MoveWirePartHead: invalid head"<<endl;
		return false;
	}

	//contents[c_to.y][c_to.x] = contents[c_from.y][c_from.x];
	/*
	contents[c_to.y][c_to.x].type = WPFOOT;
	contents[c_to.y][c_to.x].num = contents[c_from.y][c_from.x].num;

	ClearBlock(c_from);
	*/
	
	InformContentChanged();

	return true;
}

bool Board::MoveWireHead(unsigned int wnum, Coord c_from, Coord c_to)
{
	cout<<"Moving Wire "<<wnum<<" from "<<c_from.x<<","<<c_from.y<<" to "<<c_to.x<<","<<c_to.y<<endl;
	if(wires[wnum].c1 == c_from){
		wires[wnum].c1 = c_to;
	}
	else if(wires[wnum].c2 == c_from){
		wires[wnum].c2 = c_to;
	}
	else{
		cout<<"Board::MoveWirePartHead: invalid head"<<endl;
		return false;
	}

	InformContentChanged();

	return true;
}

//älä siirrä jos on yhdistettynä joku
bool Board::LameMoveWirePartHead(unsigned int wpnum, Coord c_from, Coord c_to)
{
	cout<<"LameMoveWirePartHead is DEPRECATED"<<endl;
	if(GetDirectlyConnectedCoord(c_from).size() > 0){
		cout<<"ERROR: Something connected to c_from"<<endl;
		//joku kohta on yhdistettynä tähän
		//cout<<"Board::MoveWirePartHead: Cannot move. There are things connected"<<endl;
		return false;
	}
	return MoveWirePartHead(wpnum, c_from, c_to);
}

bool Board::MovePart(unsigned int pnum, Coord c_to)
{
	Part p = parts[pnum];
	parts[pnum].SetCoord(c_to);

	InformContentChanged();

	return false;
}

/*
bool MoveBlock(unsigned int w, unsigned int h, unsigned int x1, unsigned int y1, unsigned int x2,
		unsigned int y2)
{
	//TODO: siirrä johdot ja osat listoilla
	return false;
}*/

Coord Board::FindFootNum(int num)
{
	Coord c;
	for(unsigned int x=0; x<width; x++){
		for(unsigned int y=0; y<height; y++){
			if(Content(x,y).type == PFOOT || Content(x,y).type == WPFOOT){
				if(Content(x,y).num == num){
					c.x = x;
					c.y = y;
					return c;
				}
			}
		}
	}
	c.exist = false;
	return c;
}

bool Board::CoordAreWPFootOrPointOrWireHead(Coord c)
{
	Contentblock b = Content(c);
	if(b.type != WPFOOT && b.type != WIREHEAD){
		if(b.type == PFOOT){
			int pnum = BFindPartNumWithFootNum(b.num);
			Part p = parts[pnum];
			if(p.GetFootprint()->Width()!=1 || p.GetFootprint()->Height()!=1){
				return false;
			}
		}
		else return false;
	}
	return true;
}

bool Board::AllCoordAreWPFootOrPointOrWireHead(vector<Coord> cs)
{
	for(unsigned int i=0; i<cs.size(); i++){
		if(!CoordAreWPFootOrPointOrWireHead(cs[i])) return false;
	}
	return true;
}

vector<Coord> Board::GetDirectlyConnectedCoord(Coord c)
{
	/*if(debugmessages_on)
		cout<<"Board::GetDirectlyConnectedCoord(("<<c.x<<","<<c.y<<")): got";*/
	vector<Coord> coords;
	unsigned int y = c.y;
	if((Content(c.x, c.y).type != CUT)){
		coords.push_back(c);
	}
	bool gotnothing = true;
	for(int x0 = c.x-1; x0>=0; x0--){
		if(Content(x0,y).type == CUT) break;
		else{
			Coord coord;
			coord.y = y;
			coord.x = x0;
			coords.push_back(coord);
			/*if(debugmessages_on){
				if(!gotnothing) cout<<",";
				cout<<" ("<<coord.x<<","<<coord.y<<")";
			}*/
			gotnothing = false;
		}
	}
	for(unsigned int x0 = c.x+1; x0<width; x0++){
		if(Content(x0,y).type == CUT) break;
		else{
			Coord coord;
			coord.y = y;
			coord.x = x0;
			/*if(debugmessages_on){
				if(!gotnothing) cout<<",";
				cout<<" ("<<coord.x<<","<<coord.y<<")";
			}*/
			coords.push_back(coord);
			gotnothing = false;
		}
	}
	/*if(debugmessages_on){
		if(gotnothing) cout<<" nothing";
		cout<<endl;
	}*/
	return coords;
}

//toimii mutta on aika turha (ota käyttöön jos tarvitsee)
/*
bool Board::IsDirectlyConnected(Coord c1, Coord c2)
{
	vector<Coord> coords = GetDirectlyConnectedCoord(c1);
	for(unsigned int i=0; i<coords.size(); i++){
		if(c2 == coords[i]) return true;
	}
	return false;
}
*/
void Board::GetAllConnectedCoords(Coord c, vector<Coord> *alreadysearched)
{
	//cout<<"Board::GetAllConnectedCoords(("<<c.x<<","<<c.y<<"), alreadysearched.size()="
			//<<alreadysearched.size()<<")"<<endl;
	//haetaan suoraan tähän koordinaattiin yhdistetyt johdot
	vector<Coord> dconnected = GetDirectlyConnectedCoord(c);
	//plarataan ne läpi
	for(unsigned int i=0; i<dconnected.size(); i++){
		//onko tämä koodrinaatti jo selattu läpi?
		bool is_alreadysearched = false;
		for(unsigned int a=0; a<alreadysearched->size(); a++){
			if(dconnected[i] == (*alreadysearched)[a]){
				is_alreadysearched = true;
				break;
			}
		}
		if(!is_alreadysearched){
			//ei olla jo selattu läpi
			//cout<<"not alreadysearched, adding to alreadysearched"<<endl;
			//lisätään selattujen listalle
			alreadysearched->push_back(dconnected[i]);
			//lähteekös siitä johto?
			unsigned int blockx = dconnected[i].x, blocky = dconnected[i].y;
			Contentblock b = Content(blockx,blocky);
			if(b.type == WIREHEAD){
				//cout<<"Found wire head, where goes it?"<<endl;
				//blokissa on johdon pää, minneköhän se menee?
				int wnum = BFindWireNumWithFootNum(b.num);
				//onkoa johtoa olemassakaan?
				if(wnum!=-1){
					Wire w = wires[wnum];
					//cout<<"Wire from "<<w.c1.x<<","<<w.c1.y<<" to "<<w.c2.x<<","<<w.c2.y
							//<<" found"<<endl;
					//on, katsotaan onko sen toinen pää yhteydessä toiseen blokkiin.
					//katsotaan ensin kumpi on toinen pää
					Coord otherhead;
					if(w.c1.x == blockx && w.c1.y == blocky) otherhead = w.c2;
					else if(w.c2.x == blockx && w.c2.y == blocky) otherhead = w.c1;
					else{
						cout<<"Board::GetAllConnectedCoords(): "
								"ERROR: wrong wire head: "
								<<"w.c1=("<<w.c1.x<<","<<w.c1.y<<"), ("
								<<w.c2.x<<","<<w.c2.y<<")"<<endl;
					}
					//toinen pää tiedossa, tutkitaan sen ympäristö läpi
					GetAllConnectedCoords(otherhead, alreadysearched);
				}
				else{
					cout<<"Board::GetAllConnectedCoords: ERROR: Wire head "
							"without wire found"<<endl;
				}
			}
		}
		//else cout<<"it's alreadysearched"<<endl;
	}
}

vector<Coord> Board::GetConnectedCoord(Coord c)
{
	//cout<<"==== Board::GetConnectedCoord("<<c.x<<","<<c.y<<") ===="<<endl;
	vector<Coord> coords;
	GetAllConnectedCoords(c, &coords);
	//cout<<"found "<<a.size()<<" coords"<<endl;
	return coords;
}

bool Board::IsConnected(Coord c1, Coord c2)
{
	//cout<<"Board::IsConnected "<<c1.x<<","<<c1.y<<" to "<<c2.x<<","<<c2.y<<endl;
	//vector<Coord> dconnected = GetDirectlyConnectedCoord(c1);
	vector<Coord> dconnected = GetConnectedCoord(c1);
	//onko blokki suoraan yhteydessä toiseen?
	for(unsigned int i=0; i<dconnected.size(); i++){
		//cout<<c1.x<<","<<c1.y<<" Connected directly to "
				//<<dconnected[i].x<<","<<dconnected[i].y<<endl;
		if(dconnected[i] == c2){
			//cout<<"Yes, "<<c1.x<<","<<c1.y<<" connected to "<<c2.x<<","<<c2.y<<endl;
			return true;
		}
	}
	
	//cout<<c1.x<<","<<c1.y<<" not connected to "<<c2.x<<","<<c2.y<<endl;
	return false;
}

Coord Board::GetRightHoleDirectlyConnectedToCoord(Coord tocoords, bool allowblock)
{
	//onko tässä tai oikealla tilaa reijälle?
	unsigned int y = tocoords.y;
	unsigned int x = tocoords.x;
	while(x<width){
		Contentblock b = Content(x,y);
		Contentblock bright;
		if(x<width-2) bright = Content(x+1,y);
		else bright.type = OVERBOARD;
		int space = -1;
		if(bright.type != OVERBOARD){
			bool cutcame = false;
			for(unsigned int x0 = x; x0 < width-1; x0++){
				if(Content(x0,y).type==CUT) cutcame = true;
				else if(Content(x0,y).type!=CUT && cutcame){
					space = x0 - x;
					break;
				}
			}
		}
		//cout<<"space="<<space<<endl;
		//if((!b.component_blocks || allowblock) && (b.type == CUT || b.type == HOLE)
				//&& (space >=2 || space == -1)){
		if((b.partname_blocks == "" || allowblock) && (b.type == CUT || b.type == HOLE)
				&& (space >=2 || space == -1)){
			//contents[y][x].type = HOLE;
			return MakeCoord(x, y);
		}
		//jos ohitettiin leikkaus, lopetetaan
		if(Content(x,y).type == CUT) break;
		x++;
	}
	return MakeInexistentCoord();
}

Coord Board::GetLeftHoleDirectlyConnectedToCoord(Coord tocoords, bool allowblock)
{
	//onko tässä tai vasemmalla tilaa reijälle?
	unsigned int y = tocoords.y;
	unsigned int x = tocoords.x;
	while(1){
		Contentblock b = Content(x,y);
		Contentblock bleft;
		if(x>1) bleft = Content(x-1,y);
		else bleft.type = OVERBOARD;
		int space = -1;
		if(bleft.type != OVERBOARD){
			bool cutcame = false;
			for(int x0 = x; x0 >= 0; x0--){
				//cout<<"checing contents of "<<x0<<","<<y<<endl;
				if(Content(x0,y).type==CUT) cutcame = true;
				else if(Content(x0,y).type!=CUT && cutcame){
					space = x - x0;
					break;
				}
			}
		}
		//cout<<"space="<<space<<endl;
		//if((!b.component_blocks || allowblock) && (b.type == CUT || b.type == HOLE)
				//&& (space >= 2 || space == -1)){
		if((b.partname_blocks == "" || allowblock) && (b.type == CUT || b.type == HOLE)
				&& (space >= 2 || space == -1)){
			//contents[y][x].type = HOLE;
			return MakeCoord(x, y);
		}
		//jos ohitettiin leikkaus, lopetetaan
		if(Content(x,y).type == CUT) break;
		if(x==0) break;
		x--;
	}
	return MakeInexistentCoord();
}

Coord Board::GetHoleDirectlyConnectedToCoord(Coord tocoords, bool allowblock)
{
	Coord c;
	c = GetLeftHoleDirectlyConnectedToCoord(tocoords, allowblock);
	if(c.exist) return c;
	c = GetRightHoleDirectlyConnectedToCoord(tocoords, allowblock);
	if(c.exist) return c;
	//kummallakaan puolella ei tilaa
	return MakeInexistentCoord();
}

//#define FULLDEBUG

Coord Board::GetNearestHoleDirectlyConnectedToCoord(Coord tocoords,
		unsigned int wantedx, bool allowblock)
{
#ifdef FULLDEBUG
	cout<<"Board::GetNearestHoleDirectlyConnectedToCoord(("<<tocoords.x
				<<","<<tocoords.y<<"), "<<wantedx<<")"<<endl;
#endif
	int oldxdistance = tocoords.x - wantedx;
	if(oldxdistance < 0) oldxdistance = 0 - oldxdistance;
	//cout<<"old distance is "<<oldxdistance<<endl;
	if(oldxdistance == 0){
#ifdef FULLDEBUG
		if(debugmessages_on)
			cout<<"Board::GetNearestHoleDirectlyConnectedToCoord():"
				" xdistance already 0"<<endl;
#endif
		return MakeInexistentCoord();
	}

	Coord c = MakeInexistentCoord();
	
	if(wantedx > tocoords.x){
#ifdef FULLDEBUG
		cout<<"wantedx > tocoords.x"<<endl;
#endif
		bool cutcame = false;
		for(unsigned int x=tocoords.x+1; x<=wantedx; x++){
#ifdef FULLDEBUG
			cout<<"content type in ("<<x<<","<<tocoords.y<<") is "
					<<Content(x, tocoords.y).TypeString()<<endl;
#endif

			if(Content(x, tocoords.y).type == CUT)
				cutcame = true;

			if(cutcame && Content(x+1, tocoords.y).type != CUT && Content(x+1, tocoords.y).type != OVERBOARD)
				break;
			
			Contentblock block = Content(x, tocoords.y);
			if((block.type == CUT || block.type == HOLE) && (block.partname_blocks == "" || allowblock))
				c = MakeCoord(x, tocoords.y);
			else if(cutcame)
				break;
		}
	}
	else{
#ifdef FULLDEBUG
		cout<<"wantedx <= tocoords.x"<<endl;
#endif
		bool cutcame = false;
		for(int x=tocoords.x-1; x>=(int)wantedx; x--){
#ifdef FULLDEBUG
			cout<<"content type in ("<<x<<","<<tocoords.y<<") is "
					<<Content(x, tocoords.y).TypeString()<<endl;
#endif

			if(Content(x, tocoords.y).type == CUT)
				cutcame = true;

			if(cutcame && Content(x-1, tocoords.y).type != CUT && Content(x-1, tocoords.y).type != OVERBOARD)
				break;
			
			//if((Content(x, tocoords.y).type == CUT) || (Content(x, tocoords.y).type == HOLE))
			Contentblock block = Content(x, tocoords.y);
			if((block.type == CUT || block.type == HOLE) && (block.partname_blocks == "" || allowblock))
				c = MakeCoord(x, tocoords.y);
			/*else if(cutcame)
				break;*/
		}
	}

	if(!c.exist) return c;

	if(!ConnectCoordDirectly(tocoords, c)){
		if(debugmessages_on) cout<<"Board::GetNearestHoleDirectlyConnectedToCoord(): Quite fatal error maybe!"<<endl;
		return MakeInexistentCoord();
	}

	return c;
}

Coord Board::GetOptimalHoleDirectlyConnectedToCoord(Coord fromcoords, Coord tocoords,
		bool allowblock)
{
	Coord c;
	if(fromcoords.x <= tocoords.x){
		c = GetLeftHoleDirectlyConnectedToCoord(tocoords, allowblock);
		if(c.exist) return c;
		c = GetRightHoleDirectlyConnectedToCoord(tocoords, allowblock);
		if(c.exist) return c;
	}
	else{
		c = GetRightHoleDirectlyConnectedToCoord(tocoords, allowblock);
		if(c.exist) return c;
		c = GetLeftHoleDirectlyConnectedToCoord(tocoords, allowblock);
		if(c.exist) return c;
	}
	//kummallakaan puolella ei tilaa
	return MakeInexistentCoord();
}

Coord Board::GetHoleConnectedToCoord(Coord tocoords, bool allowblock)
{
	//cout<<"Board::GetHoleConnectedToCoord("<<tocoords.x<<","<<tocoords.y<<")"<<endl;
	//löytyisikö suoraan yhdistetty reikä?
	Coord a = GetHoleDirectlyConnectedToCoord(tocoords, allowblock);
	if(a.exist) return a; //jees
	//ei, plarataan joka ikinen reikä ja katsotaan onko jostain jollain tapaa yhteys
	//cout<<"Searching whole board"<<endl;
	for(unsigned int y=0; y<height; y++){
		for(unsigned int x=0; x<width; x++){
			if(IsConnected(MakeCoord(x, y), tocoords)){
				//cout<<"Found connected block "<<x<<","<<y<<endl;
				Contentblock b = Content(x, y);
				Contentblock l = Content(x-1, y);
				Contentblock r = Content(x+1, y);
				if(b.type==CUT){
					//cout<<"Found CUT-typed block "<<x<<","<<y<<": ";
					Coord c_connected = GetHoleDirectlyConnectedToCoord(MakeCoord(x,y),
							allowblock);
					if(c_connected.exist){
						//cout<<"Got hole directly connected to it: "<<c_connected.x<<","<<c_connected.y
								//<<endl;
						return c_connected;
					}
					//else cout<<"Couldn't find free hole connected to it"<<endl;
				}
				else{
					//cout<<"Found already used block "<<x<<","<<y<<endl;
				}
			}
		}
	}
	/*cout<<"Board::GetHoleConnectedToCoord(("<<tocoords.x<<","<<tocoords.y
			<<")): Could not get connected hole anywhere"<<endl;*/
	return MakeInexistentCoord();
}

/*
 * fromcoords: paikka, johon yhdistetty reikä halutaan
 * tocoords: paikka, jota lähin reikä halutaan
 */
Coord Board::GetClosestPossibleHoleConnectedToCoord(Coord fromcoords, Coord tocoords,
		bool allowblock)
{
	//cout<<"Board::GetClosestPossibleHoleConnectedToCoord() called"<<endl;

	double mindistance = 0;
	Coord minc = MakeInexistentCoord();
	vector<Coord> cs = GetConnectedCoord(tocoords);
	//cout<<"cs="; DumpCoords(cs); cout<<endl;
	for(unsigned int i=0; i<cs.size(); i++){
		Coord c = GetOptimalHoleDirectlyConnectedToCoord(fromcoords, cs[i], allowblock);
		if(c.exist){
			//cout<<"looking at "<<c.String()<<endl;
			double distance = Distance(fromcoords, c);
			if(!minc.exist || distance < mindistance){
				/*cout<<"distance is shorter"<<endl;
				vector<Coord> coords = GetDirectlyConnectedCoord(c);
				cout<<"coordinates directly connected to "<<c.String()<<": "; DumpCoords(coords); cout<<"... ";
				bool was = false;
				for(unsigned int i=0; i<not_directly_connected_to.size(); i++){
					if(not_directly_connected_to[i] == c){
						cout<<not_directly_connected_to[i].String()<<" is not allowed to be connected to."<<endl;
						was = true;
						goto was_bad_hole;
					}
				}
				cout<<"Is allowed to connect to."<<endl;
was_bad_hole:
				if(was==true) continue;*/
				minc = c;
				mindistance = distance;
			}
			//else cout<<"distance isn't shorter"<<endl;
		}
	}
	//cout<<minc.x<<","<<minc.y<<" is nearest free to "<<fromcoords.x<<","<<fromcoords.y<<endl;
	return minc;
}

bool Board::CanConnectCoordDirectly(Coord c1, Coord c2)
{
	/*if(debugmessages_on)
		cout<<"Board::CanConnectCoordDirectly(("<<c1.x<<","<<c1.y<<"),("
				<<c2.x<<","<<c2.y<<"))"<<endl;*/

	if(!c1.exist || !c2.exist){
		cout<<"Board::CanConnectCoordDirectly(): ERROR: Coord doesn't exist"<<endl;
		return false;
	}

	if(c1.y != c2.y){
		/*if(debugmessages_on)
			cout<<"Board::CanConnectCoordDirectly(): cannot connect (different y)"<<endl;*/
		return false;
	}

	unsigned int y = c1.y;
	unsigned int start = c1.x < c2.x ? c1.x : c2.x;
	unsigned int stop = c1.x > c2.x ? c1.x : c2.x;
	//cout<<"y = "<<y<<" start = "<<start<<" stop = "<<stop<<endl;
	unsigned int changes = 0;
	bool lastwascut = Content(start, y).type == CUT;
	for(unsigned int x = start+1; x<stop; x++){
		Contentblock b = Content(x, y);
		if(lastwascut){
			if(b.type != CUT){
				lastwascut = false;
				changes++;
			}
		}
		else{
			if(b.type == CUT){
				lastwascut = true;
				changes++;
			}
		}
		//TODO: öö vai pelkkä changes >= 3?
		if((changes >= 2 && b.type != HOLE && b.type != PFOOT && b.type != WPFOOT && b.type != WIREHEAD) || changes >= 3){
			/*if(debugmessages_on)
				cout<<"Board::CanConnectCoordDirectly: cannot connect: "
						" two changes came"<<endl;*/
			return false;
		}
	}
	/*if(debugmessages_on)
		cout<<"Board::CanConnectCoordDirectly: can connect"<<endl;*/
	return true;
}

/*vector<Coord> Board::GetAllDirectlyConnectableHoles(Coord c1)
{
	//cout<<"Board::GetAllDirectlyConnectableHoles(("<<c1.x<<","<<c1.y<<"))"<<endl;
	vector<Coord> cs;
	unsigned int y = c1.y;
	for(unsigned int x=0; x<width; x++){
		Coord c2 = MakeCoord(x, y);
		Coord c2l = MakeCoord(x-1, y);
		Coord c2r = MakeCoord(x+1, y);
		Contentblock b = Content(c2);
		Contentblock l = Content(c2l);
		Contentblock r = Content(c2r);
		if(b.type == HOLE || b.type == CUT){
			//cout<<"hole || cut @ "<<c2.x<<","<<c2.y<<endl;
			if(x != c1.x && (l.type == CUT || l.type == OVERBOARD)
					&& (r.type == CUT || r.type == OVERBOARD)){
				//cout<<"found "<<c2.x<<","<<c2.y<<": ";
				if(CanConnectCoordDirectly(c1, c2)){
					cs.push_back(c2);
					cout<<"Can connect directly to ("<<c2.x<<","<<c2.y<<")"<<endl;
				}
				//else cout<<"Can't connect directly"<<endl;
			}
		}
	}
	return cs;
}*/

bool Board::ConnectCoordDirectly(Coord c1, Coord c2)
{
	if(c1==c2){
		if(debugmessages_on) cout<<"Board::ConnectCoordDirectly(): Coordinates are same -> we say it is now connected"<<endl;
		return true;
	}
	if(CanConnectCoordDirectly(c1, c2)){
		int y = c1.y;
		if(debugmessages_on) cout<<"Board::ConnectCoordDirectly(): Connecting ("
				<<c1.x<<","<<y<<") and ("<<c2.x<<","<<y<<") directly"<<endl;
		DConn dc(c1, c2, dconnnumcounter);
		dconns.push_back(dc);
		dconnnumcounter++;
		InformContentChanged();
		/*unsigned int start = c1.x < c2.x ? c1.x : c2.x;
		unsigned int stop = c1.x > c2.x ? c1.x : c2.x;
		for(unsigned int x = start; x<=stop; x++){
			if(Content(x,y).type == CUT) contents[y][x].type = HOLE;
		}*/
		return true;
	}
	else{
		cout<<"Board::ConnectCoordDirectly(): ERROR: Can't connect ("
				<<c1.x<<","<<c1.y<<") and ("<<c2.x<<","<<c1.y<<") directly"<<endl;
	}
	//cout<<"Board::ConnectCoordDirectly(): disabled"<<endl;
	return false;
}

bool Board::ConnectCoord(Coord c1, Coord c2)
{
	if(debugmessages_on) cout<<"Board::ConnectCoord(("<<c1.x<<","<<c1.y<<"),("
			<<c2.x<<","<<c2.y<<"))"<<endl;
	if(!c1.exist || !c2.exist){
		cout<<"Board::ConnectCoord(): ERROR: coords don't exist"<<endl;
		return false;
	}
	//yritetään hakea lähimmän matkan päässä toisistaan ja suoraan
	//yhdistettävissä olevat pisteet
	unsigned int mind = 0;
	Coord b1=MakeInexistentCoord(), b2=MakeInexistentCoord();
	vector<Coord> cc1 = GetConnectedCoord(c1);
	vector<Coord> cc2 = GetConnectedCoord(c2);
	for(unsigned int i=0; i<cc1.size(); i++){
		//if(debugmessages_on) cout<<cc1[i].String()<<" -> ";
		for(unsigned int j=0; j<cc2.size(); j++){
			//if(debugmessages_on) cout<<cc2[j].String()<<",";
			if(CanConnectCoordDirectly(cc1[i], cc2[j])){
				double d = Distance(cc1[i], cc2[j]);
				if(d < mind || !b1.exist){
					mind = d;
					b1 = cc1[i];
					b2 = cc2[j];
				}
			}
		}
		//cout<<endl;
	}
	if(b1.exist){
		if(ConnectCoordDirectly(b1, b2)){
			cout<<"Board::ConnectCoord(): SUCCESS: now connected directly"<<endl;
			assert(IsConnected(c1,c2));
			return true;
		}
		else assert(0);
	}

	//ei voi yhdistää suoraan, kokeillaan käyttää johtoa

	//cout<<"Board::ConnectCoord(("<<c1.x<<","<<c1.y<<"),("<<c2.x<<","<<c2.y<<"))"<<endl;
	//cout<<"Connecting "<<c1.x<<","<<c1.y<<" and "<<c2.x<<","<<c2.y<<" with wire"<<endl;
	
	Coord c_wire_a_1 = GetClosestPossibleHoleConnectedToCoord(c2, c1, WIRE_ALLOW_BLOCKED);
	Coord c_wire_a_2 = GetClosestPossibleHoleConnectedToCoord(c_wire_a_1, c2, WIRE_ALLOW_BLOCKED);
	Coord c_wire_b_2 = GetClosestPossibleHoleConnectedToCoord(c1, c2, WIRE_ALLOW_BLOCKED);
	Coord c_wire_b_1 = GetClosestPossibleHoleConnectedToCoord(c_wire_b_1, c1, WIRE_ALLOW_BLOCKED);

	Coord c_wire_1, c_wire_2;

	if(Distance(c_wire_a_1, c_wire_a_2) < Distance(c_wire_b_1, c_wire_b_2)
			&& c_wire_a_1.exist && c_wire_a_2.exist){
		c_wire_1 = c_wire_a_1;
		c_wire_2 = c_wire_a_2;
	}
	else if(c_wire_b_1.exist && c_wire_b_2.exist){
		c_wire_1 = c_wire_b_1;
		c_wire_2 = c_wire_b_2;
	}
	else{
		cout<<"Board::ConnectCoord(): FAIL: can't find free holes for connecting"<<endl;
		return false;
	}

	//tungetaan johto
	
	if(c_wire_1.exist && c_wire_2.exist){
		cout<<"Board::ConnectCoord(): Connecting with wire ("<<c_wire_1.String()<<"->"<<c_wire_2.String()<<")... ";
		//cout<<"wire from "<<c_wire1.x<<","<<c_wire1.y<<" to "<<c_wire2.x<<","<<c_wire2.y<<endl;
		Wire wire(c_wire_1, c_wire_2, wirenumcounter);
		if(PutWire(wire) == false){
			cout<<"FAILED!"<<endl;
			return false;
		}
		wirenumcounter++;
		cout<<"success."<<endl;
		return true;
	}
	else{
		cout<<"Board::ConnectCoord(): FATAL: wire doesn't exist"<<endl;
		return false;
	}
	//cout<<"Board::ConnectCoord(): FAIL"<<endl;
	//return false;
}

double Board::ConnectionScore(Coord c1, Coord c2)
{
	if(!c1.exist || !c2.exist){
		return 0.0;
	}
	else if(CanConnectCoordDirectly(c1,c2)){
		return 10.0;
	}
	else{
		return 1.0/Distance(c1,c2);
	}
}

double Board::ConnectionScore(Part &p, Coord c)
{
	double score = 0.0;
	vector<Foot> foots = p.GetFootprint()->Foots();
	//selataan osan jalat läpi
	for(unsigned int i=0; i<foots.size(); i++){
		//lasketaan tämän jalan koordinaatit levyllä
		Coord pfc = c;
		pfc.x += foots[i].x;
		pfc.y += foots[i].y;
		//haetaan jalkojen numerot, joihin tämän jalan pitäisi olla yhteydessä
		vector<int> footnums_to_connect = circuitp->GetFootNumsConnected(foots[i].number);
		if(CONNECTION_SCORE_ONLY_MEASURE_CLOSEST_FEET){
			//etsitään ko. jaloista lähimpänä oleva
			double mind = 0;
			Coord c2 = MakeInexistentCoord();
			for(unsigned int j=0; j<footnums_to_connect.size(); j++){
				Coord fc = FindFootNum(footnums_to_connect[j]);
				if(fc.exist){
					double distance = Distance(pfc, fc);
					if(distance < mind || !c2.exist){
						mind = distance;
						c2 = fc;
					}
				}
			}
			if(c2.exist){
				score += ConnectionScore(pfc, c2);
			}
		}
		else{
			//lisätään connectionscoret tästä jalasta niihin jalkoihin yhteen
			for(unsigned int j=0; j<footnums_to_connect.size(); j++){
				Coord fc = FindFootNum(footnums_to_connect[j]);
				if(fc.exist){
					score += ConnectionScore(pfc, fc);
				}
			}
		}
	}
	return score;
}


///////////////////////////////////////////////////////////////////////////////////7


#define OPTIMIZE_CHUNK_ORDERS_MAX_LOOPCOUNT 2

int Board::OptimizeChunkOrders()
{
	//optimoidaan yhteen yhdistettyjen johtojen, wirepartsien ja 1x1-parttien
	//järjestyksiä
	/*cout<<"========================================================"<<endl
			<<"Optimizing wire, wirepart head and point groups' orders"<<endl
			<<"========================================================"<<endl;*/
	cout<<"Board::OptimizeChunkOrders()"<<endl;
	bool checkagain, didsomething = false;
	unsigned int loopcount = 0;
	do{
		if(debugmessages_on) cout<<"|||LOOP|||"<<endl;
		checkagain = false;
		/*if(debugmessages_on){
			cout<<"--------------------"<<endl;
			Draw();
			cout<<">>>>>>>>>>>>>>>>>"<<endl;
		}*/
		for(unsigned int y=0; y<height; y++){
			for(unsigned int x=0; x<width; x++){
				Contentblock block = Content(x,y);
				Coord cc;
				cc.x = x;
				cc.y = y;
				//onko tässä johto-osan jalka?
				if(block.type == WPFOOT){
					//haetaan koordinaatit joihin se on levyllä yhteydessä
					vector<Coord> cs_connected_unsorted = GetDirectlyConnectedCoord(cc);
					unsigned int num_connected = cs_connected_unsorted.size();
					//onko se yhteydessä mihinkään levyllä?
					if(num_connected == 1){
						//ei, sitä voidaan olla esim. laittamassa siihen, joten ei kosketa siihen
						/*if(debugmessages_on) cout<<"(wirepart "<<wpnum<<" \""
								<<wparts[wpnum].Name()<<"\" connected to nothing)"<<endl;*/
						continue;
					}

					//järjestetään vierekkäin olevien lista x:n mukaan, pienin ensimmäiseksi
					vector<Coord> cs_connected;
					while(!cs_connected_unsorted.empty()){
						int mostleftx = 0;
						int num = -1;
						for(unsigned int i=0; i<cs_connected_unsorted.size(); i++){
							int x;
							if(!cs_connected_unsorted[i].exist){
								cout<<"*** ERROR: !cs_connected_unsorted[i].exist"<<endl<<endl;
								return -1;
							}
							else{
								x = cs_connected_unsorted[i].x;
							}
							if(x < mostleftx || num == -1){
								mostleftx = x;
								num = i;
							}
						}
						/*cout<<"Adding ("<<cs_connected_unsorted[num].x<<","
								<<cs_connected_unsorted[num].y
								<<") to cs_connected"<<endl;*/
						cs_connected.push_back(cs_connected_unsorted[num]);
						cs_connected_unsorted.erase(cs_connected_unsorted.begin()+num);
					}


					//TODO


#if 1
					//jos se on yhteydessä ainoastaan wirepartseihin, yhden kokoisin osiin
					//tai johdonpäihin
					if(AllCoordAreWPFootOrPointOrWireHead(cs_connected_unsorted)){
						if(debugmessages_on) cout<<"FOUND WirePart heads or 1x1-parts or WireHeads connected to "
								"each other at ("<<cc.x<<","<<cc.y<<")"<<endl;
						
						//katsotaan onko joukossa lukittuja osia
						bool waslocked = false;
						Coord lockedcoord;
						for(unsigned int i=0; i<cs_connected_unsorted.size(); i++){
							Contentblock b = Content(cs_connected_unsorted[i]);
							if(b.type == PFOOT){
								int pnum = BFindPartNumWithFootNum(b.num);
								if(pnum != -1){
									if(parts[pnum].Locked()){
										lockedcoord = cs_connected_unsorted[i];
										waslocked = true;
										break;
									}
								}
							}
						}
						if(waslocked){
							if(debugmessages_on) cout<<"A locked part at "<<lockedcoord.String()<<". Not moving anything"<<endl;
							continue;
						}

						//kaivellaan kaikkien osien toisten päiden koordinaatit
						//listaan päiden uutta järjestelyä varten. 1x1-osien
						//koordinaatteja ei ole (!exist)
						vector<Coord> cs_otherheads;
						if(debugmessages_on){
							cout<<"cs_connected_unsorted has: ";
							DumpCoords(cs_connected_unsorted);
							cout<<endl;
						}
						for(unsigned int i=0; i<cs_connected_unsorted.size(); i++){
							Coord thisheadc = cs_connected_unsorted[i];
							Contentblock b = Content(thisheadc);
							Coord otherheadc = MakeInexistentCoord();
							if(b.type == WPFOOT){
								int wpnum = BFindWirePartNumWithFootNum(
										Content(thisheadc).num);
								otherheadc = wparts[wpnum].OtherHeadCoord(thisheadc);
								if(!otherheadc.exist){
									if(debugmessages_on) cout<<"(wirepart with inexistent head found: num="<<wpnum<<" name="<<wparts[wpnum].Name()<<". hopefully it is being put on the board at the moment)"<<endl;
									continue;
								}
							}
							else if(b.type == WIREHEAD){
								int wnum = BFindWireNumWithFootNum(
										Content(thisheadc).num);
								otherheadc = wires[wnum].OtherHeadCoord(thisheadc);
								if(!otherheadc.exist){
									cout<<"ERROR: Wire with inexistent head (num="<<wnum<<")"<<endl<<endl;
									return -1;
								}
							}
							else if(b.type == PFOOT){
								//ok
							}
							else{
								cout<<"Board::OptimizeChunkOrders(): FATAL: totally wrong content @ "<<thisheadc.String()<<" b.type="<<b.TypeString()<<" (Should be PFOOT, WPFOOT or WIREHEAD)"<<endl;
								return -1;
							}
							if(debugmessages_on){
								cout<<"("<<thisheadc.String()<<")";
								cout<<"->("<<otherheadc.String()<<")"<<endl;
							}
							//if(otherheadc.exist){
							cs_otherheads.push_back(otherheadc);
							//}
						}
						//cout<<endl;

						//järjestetään vierekkäin olevien lista x:n mukaan, pienin ensimmäiseksi
						vector<Coord> cs_connected;
						while(!cs_connected_unsorted.empty()){
							int mostleftx = 0;
							int num = -1;
							for(unsigned int i=0; i<cs_connected_unsorted.size(); i++){
								int x;
								if(!cs_connected_unsorted[i].exist){
									cout<<"*** ERROR: !cs_connected_unsorted[i].exist"<<endl<<endl;
									return -1;
								}
								else{
									x = cs_connected_unsorted[i].x;
								}
								if(x < mostleftx || num == -1){
									mostleftx = x;
									num = i;
								}
							}
							/*cout<<"Adding ("<<cs_connected_unsorted[num].x<<","
									<<cs_connected_unsorted[num].y
									<<") to cs_connected"<<endl;*/
							cs_connected.push_back(cs_connected_unsorted[num]);
							cs_connected_unsorted.erase(cs_connected_unsorted.begin()+num);
						}

						//haetaan yhdistetyistä eniten vasemmalla oleva
						/*int mostleftx0 = -1;
						for(unsigned int i=0; i<cs_connected.size(); i++){
							if(mostleftx0 == -1 || (int)cs_connected[i].x < mostleftx0)
									mostleftx0 = cs_connected[i].x;
						}*/
						//int mostleftx0 = cs_connected[0].x;
						//Coord centercoords = MakeCoord(mostleftx0 /*+ cs_connected.size()/2*/,
						//		cs_connected[0].y);
						//if(debugmessages_on) cout<<"centercoords = ("<<centercoords.x<<","<<centercoords.y<<")"<<endl;

						//laitetaan vierekkäin olevat päät hyvään järjestykseen
						//(toitsen päiden x:n mukaan)
						
						vector<Coord> cs_otherheads_old = cs_otherheads;
						vector<Coord> cs_otherheads_new;
						vector<Coord> cs_connected_old = cs_connected;
						vector<Coord> cs_connected_new;

#define CHUNKORDER_BRUTEFORCE_MAX_HEAD_COUNT 6

						//if(cs_connected.size() <= CHUNKORDER_BRUTEFORCE_MAX_HEAD_COUNT){
						if(0){
							if(debugmessages_on) cout<<"Bruteforcing"<<endl;
							vector<unsigned int> bestorder, temporder;
							for(unsigned int i=0; i<cs_connected.size(); i++){
								temporder.push_back(i);
							}
							double bestdistance = 0;
							for(unsigned int i=0; i<temporder.size(); i++){
								bestdistance += Distance(cs_connected_old[temporder[i]], cs_otherheads_old[i]);
							}
							bool found_better = false;
							if(debugmessages_on) cout<<"going in while loop"<<endl;
							while(next_permutation(temporder.begin(), temporder.end())){
								double totaldistance = 0;
								for(unsigned int i=0; i<temporder.size(); i++){
									totaldistance += Distance(cs_connected_old[temporder[i]], cs_otherheads_old[i]);
								}
								if(debugmessages_on) cout<<"totaldistance="<<totaldistance<<" bestdistance="<<bestdistance<<endl;
								if(totaldistance < bestdistance || bestdistance == -1){
									bestdistance = totaldistance;
									bestorder = temporder;
									found_better = true;
								}
							}
							if(debugmessages_on) cout<<"bestdistance="<<bestdistance<<" found_better = "<<found_better<<endl;
							if(found_better){
								for(unsigned int i=0; i<bestorder.size(); i++){
									cs_connected_new.push_back(cs_connected_old[bestorder[i]]);
								}
							}
						}
						else{
							while(!cs_connected.empty()){
								int mostleftx = 0;
								int num = -1;
								for(unsigned int i=0; i<cs_connected.size(); i++){
									int x;
									if(!cs_otherheads[i].exist){
										//TODO: onkohan tämä nyt ihan järkevä ratkaisu?
										//ei tee hyvää ainakaan lähintä paikkaa hakeville jutuille
										//(tällä paikka saisi olla mikä vain)
										//eikun tämähän juuri hakee sitä :-o selvitä asia!
										//ahaa, tämä laittaa ne vain kaikkie oikealle puolelle.
										//onkohan se järkevää? ei tietenkään ainakaan kaikkein
										//optimaalisinta.
										x = width; //(viimeinen mahdollinen x) + 1
									}
									else{
										x = cs_otherheads[i].x;
									}
									if(x < mostleftx || num == -1){
										mostleftx = x;
										num = i;
									}
								}
								if(debugmessages_on) cout<<"Adding ("<<cs_connected[num].x<<","
										<<cs_connected[num].y<<") to cs_connected_new"<<endl;
								cs_connected_new.push_back(cs_connected[num]);
								cs_connected.erase(cs_connected.begin()+num);
								cs_otherheads_new.push_back(cs_otherheads[num]);
								cs_otherheads.erase(cs_otherheads.begin()+num);
							}
						}
						if(debugmessages_on){
							cout<<"cs_otherheads_old: ";
							DumpCoords(cs_otherheads_old);
							cout<<" cs_otherheads_new: ";
							DumpCoords(cs_otherheads_new);
							cout<<endl<<"cs_connected_old: ";
							DumpCoords(cs_connected_old);
							cout<<" cs_connected_new: ";
							DumpCoords(cs_connected_new);
							cout<<endl;
						}
						
						//=====================================
						//ei jatketa jos paras järjestys oli jo
						//=====================================
						
						bool different_order = false;
						for(unsigned int i=0; i<cs_connected_new.size(); i++){
							if(cs_connected_new[i] != cs_connected_old[i]){
								different_order = true;
								break;
							}
						}
						if(!different_order){
							if(debugmessages_on) cout<<"Got same order as before, skipping"<<endl;
							continue;
						}
						if(debugmessages_on)
							cout<<"Got different order than before, continuing"<<endl;
						
						
						//liikutellaan osat uusille paikoilleen
						for(unsigned int i=0; i<num_connected; i++){
							//head old coordinates ja head new coordinates
							Coord hoc = cs_connected_old[i];
							Coord hnc = cs_connected_new[i];
							/*cout<<"Moving ("<<hoc.x<<","<<hoc.y<<") to ("
									<<hnc.x<<","<<hnc.y<<")"<<endl;*/
							//Coord hnc = MakeCoord(mostleftx0 + i, y);
							Contentblock b = Content(hoc);
							if(b.type == WPFOOT){
								//cout<<"block foot num is "<<b.num<<endl;
								int wpnum = BFindWirePartNumWithFootNum(b.num);
								WirePart wp = wparts[wpnum];
								if(debugmessages_on) cout<<"Moving wpart "
										<<wpnum<<" \""<<wp.Name()<<"\" from ("
										<<hoc.x<<","<<hoc.y<<") to ("<<hnc.x<<","
										<<hnc.y<<")"<<endl;
								//MoveWirePartHead(wpnum, hoc, hnc);
								if(wparts[wpnum].C1() == hoc){
									wparts[wpnum].SetCoord(hnc, wparts[wpnum].C2());
								}
								else if(wparts[wpnum].C2() == hoc){
									wparts[wpnum].SetCoord(wparts[wpnum].C1(), hnc);
								}
								else{
									cout<<"invalid WirePart head (error id 323402)"<<endl<<endl;
									return -1;
								}
							}
							else if(b.type == PFOOT){
								//tämän pitäisi olla tässä vaiheessa 1x1-kokoinen osa
								int pnum = BFindPartNumWithFootNum(b.num);
								Part p = parts[pnum];
								if(debugmessages_on) cout<<"Moving part \""
										<<parts[pnum].Name()<<"\" from ("<<hoc.x
										<<","<<hoc.y<<") to ("<<hnc.x<<","<<hnc.y
										<<")"<<endl;
								//MovePart(pnum, hnc);
								parts[pnum].SetCoord(hnc);
							}
							else if(b.type == WIREHEAD){
								int wnum = BFindWireNumWithFootNum(
										b.num);
								if(debugmessages_on) cout<<"Moving wire number "
										<<wnum<<" from ("<<hoc.x<<","
										<<hoc.y<<") to ("<<hnc.x<<","<<hnc.y
										<<")"<<endl;
								//MoveWireHead(wnum, hoc, hnc);
								if(wires[wnum].c1 == hoc){
									wires[wnum].c1 = hnc;
								}
								else if(wires[wnum].c2 == hoc){
									wires[wnum].c2 = hnc;
								}
								else{
									cout<<"invalid wire head (id 22414)"<<endl<<endl;
									return -1;
								}
							}
							else{
								cout<<"ERROR: this shouldn't happen (id 3)"<<endl<<endl;
								return -1;
							}
						}

						InformContentChanged();
						
						if(debugmessages_on)
							cout<<"Moved a couple of wires, WirePart heads and 1x1 Parts"<<endl;
						checkagain = true;
					}
#endif
				}
			}
		}
		if(checkagain) didsomething = true;
		loopcount++;
	} while(checkagain && loopcount <= OPTIMIZE_CHUNK_ORDERS_MAX_LOOPCOUNT);

	if(debugmessages_on) cout<<"Board::OptimizeChunkOrders(): Done."<<endl<<endl;

	if(didsomething) return 1;
	else return 0;
}

int Board::OptimizeConnectionPlaces()
{
	//optimoidaan yhteen yhdistettyjen wirepartsien ja 1x1-parttien yhdistyspaikkoja
	/*cout<<"========================================================"<<endl
			<<"Optimizing wire, wirepart head and point groups' places"<<endl
			<<"========================================================"<<endl;*/
	cout<<"Board::OptimizeConnectionPlaces()"<<endl;
	bool checkagain, didsomething = false;
	do{
		if(debugmessages_on) cout<<"|||LOOP|||"<<endl;
		checkagain = false;
		/*if(debugmessages_on){
			cout<<"--------------------"<<endl;
			Draw();
			cout<<">>>>>>>>>>>>>>>>>"<<endl;
		}*/
		for(unsigned int y=0; y<height; y++){
			for(unsigned int x=0; x<width; x++){
				Contentblock block = Content(x,y);
				Coord cc;
				cc.x = x;
				cc.y = y;
				//onko tässä johto-osan jalka?
				if(block.type == WPFOOT){
					//haetaan koordinaatit joihin se on levyllä yhteydessä
					vector<Coord> cs_connected = GetDirectlyConnectedCoord(cc);
					//onko se yhteydessä mihinkään levyllä?
					if(cs_connected.size() == 1){
						//ei, mutta kyllä sen pitäisi olla jos kaikki olisi ok :o
						int wpnum = BFindWirePartNumWithFootNum(Content(cs_connected[0]).num);
						if(debugmessages_on) cout<<"WARNING: wirepart "<<wpnum<<" ("<<wparts[wpnum].Name()
								<<") connected to nothing"<<endl;
						continue;
					}
					//jos se on yhteydessä ainoastaan wirepartseihin tai yhden kokoisin osiin
					//tai johdonpäihin
					if(AllCoordAreWPFootOrPointOrWireHead(cs_connected)){
						//kokeillaan liikutella tätä liitoskohtaa vähän optimaalisempaan paikkaan

						if(debugmessages_on) cout<<"Found WirePart heads or 1x1-parts or WireHeads connected to "
								"each other at ("<<cc.x<<","<<cc.y<<")"<<endl;
						
						//katsotaan onko joukossa lukittuja osia
						bool waslocked = false;
						Coord lockedcoord;
						for(unsigned int i=0; i<cs_connected.size(); i++){
							Contentblock b = Content(cs_connected[i]);
							if(b.type == PFOOT){
								int pnum = BFindPartNumWithFootNum(b.num);
								if(pnum != -1){
									if(parts[pnum].Locked()){
										lockedcoord = cs_connected[i];
										waslocked = true;
										break;
									}
								}
							}
						}
						if(waslocked){
							if(debugmessages_on) cout<<"A locked part at "<<lockedcoord.String()<<". Not moving anything"<<endl;
							continue;
						}
						
						//haetaan yhdistetyistä eniten vasemmalla oleva
						int mostleftx = -1;
						for(unsigned int i=0; i<cs_connected.size(); i++){
							if(mostleftx == -1 || (int)cs_connected[i].x < mostleftx)
									mostleftx = cs_connected[i].x;
						}
						Coord centercoords = MakeCoord(mostleftx /*+ cs_connected.size()/2*/,
								cs_connected[0].y);
						//cout<<"centercoords = ("<<centercoords.x<<","<<centercoords.y<<")"<<endl;
						
						//=====================================================
						//kaivellaan wirepartsien toisten päiden, jotka ovat
						//kiinni kiinteissä osissa, koordinaatteja otherheadcs-
						//listaan
						//=====================================================
						bool add_everything = false;
						vector<Coord> otherheadcs;
try_adding_again:
						otherheadcs.clear();

						//lisätään levyn keskusta yhdeksi vertailukoordinaatiksi
						//otherheadcs.push_back(GetApproxBoardCentre());
						
						#if 1
						for(unsigned int i=0; i<cs_connected.size(); i++){
							Coord thisheadc = cs_connected[i];
							Contentblock b = Content(cs_connected[i]);
							//HUOM: ei välitetä johtojen toisten päiden paikoista,
							//johdot saa olla pitkiä
							if(b.type == WPFOOT/* || b.type == WIREHEAD*/){
								Coord otherheadc;
								if(b.type == WPFOOT){
									int wpnum = BFindWirePartNumWithFootNum(
											Content(thisheadc).num);
									otherheadc = wparts[wpnum].OtherHeadCoord(thisheadc);
								}
								/*else if(b.type == WIREHEAD){
									int wnum = BFindWireNumWithFootNum(
											Content(thisheadc).num);
									otherheadc = wires[wnum].OtherHeadCoord(thisheadc);
								}*/
								else{
									cout<<"ERROR 349892134"<<endl<<endl;
									return -1;
								}
								if(!otherheadc.exist){
									cout<<"ERROR: No head found (id 2349872394)"<<endl<<endl;
									return -1;
								}
								//jos siihen on yhdistetty jotain muutakin kuin
								//wpfootseja tai pointteja tai johtoja (ts.
								//liikuteltavia osia), joiden mukaan kannattaa
								//kokeilla siirtää, lisätään se otherhead-listaan
								if(!AllCoordAreWPFootOrPointOrWireHead(
										GetDirectlyConnectedCoord(otherheadc))
										|| add_everything){
									/*cout<<"adding "<<wp_otherheadc.x<<","<<wp_otherheadc.y
											<<" to otherheadcs"<<endl;*/
									otherheadcs.push_back(otherheadc);
								}
							}
							else if(b.type != PFOOT && b.type != WIREHEAD){
								cout<<"*** ERROR: content shouldn't be anything else"
										" than (W)PFOOT or WIREHEAD"<<endl<<endl;
								return -1;
							}
						}
						#endif

						if(otherheadcs.size()==0){
							if(debugmessages_on) cout<<"No head is connected to a static part"<<endl;
							///*
							if(!add_everything){
								if(debugmessages_on) cout<<"adding every head (those not connected to static parts too)"<<endl;
								add_everything = true;
								goto try_adding_again;
							}
							cout<<"ERROR: this shouldn't happen (id 329148)"<<endl<<endl;
							return -1;
							//*/

							/*
							cout<<"using approximate board centre"<<endl;

							//lisätään levyn keskusta yhdeksi vertailukoordinaatiksi
							otherheadcs.push_back(GetApproxBoardCentre());
							*/

							/*cout<<"using first wpart's other"<<endl;
							Coord wpartcoords = MakeInexistentCoord();
							for(unsigned int i=0; i<cs_connected.size(); i++){
								Contentblock b = Content(cs_connected[i]);
								if(b.type == WPFOOT){
									wpartcoords = cs_connected[i];
									break;
								}
							}
							if(wpartcoords.exist){
								//löydettiin wirepart
								int wpnum = BFindWirePartNumWithFootNum(Content(cs_connected[0]).num);
								Coord c_other = wparts[wpnum].OtherHeadCoord(cs_connected[0]);
								if(!c_other.exist){
									cout<<"WirePart's other head not found"<<endl;
									continue;
								}
								otherheadcs.push_back(c_other);
							}
							else{
								cout<<"Wut? Only points connected to each other?"<<endl;
								//Ei löydetty wireparttia, levyllä on siis pelkkiä pointteja
								//yhdistettynä toisiinsa. Ei tehdä mitään.
								continue;
							}*/
						}

						/*cout<<"compared to ";
						for(unsigned int i=0; i<otherheadcs.size(); i++){
							cout<<"("<<otherheadcs[i].x<<","<<otherheadcs[i].y<<"), ";
						}
						cout<<endl;*/
						
						if(otherheadcs.size()==0) continue;

						Coord newcoords = FindClosestPossibleFreePlace(otherheadcs,
							cs_connected.size(), 1, 1);
						
						if(newcoords.exist){
							double olddistance = Distance(centercoords, otherheadcs);
							double newdistance = Distance(newcoords, otherheadcs);
							if(debugmessages_on) cout<<"New place: ("<<newcoords.x<<","<<newcoords.y<<")"<<endl;
							if(debugmessages_on) cout<<"New distance is "<<newdistance<<", old is "<<olddistance<<endl;
							//jos päästään lähemmäs
							if(newdistance < olddistance){
								if(debugmessages_on) cout<<"Found place with smaller distance"<<endl;
								//liikutellaan osat uusille paikoilleen
								for(unsigned int i=0; i<cs_connected.size(); i++){
									Coord hc = cs_connected[i];
									Coord hnc = MakeCoord(newcoords.x+i, newcoords.y);
									Contentblock b = Content(hc);
									if(b.type == WPFOOT){
										//cout<<"block foot num is "<<b.num<<endl;
										int wpnum = BFindWirePartNumWithFootNum(b.num);
										WirePart wp = wparts[wpnum];
										if(debugmessages_on) cout<<"wpart "<<wpnum<<" ("
												<<wp.Name()<<") from "<<hc.x<<","
												<<hc.y<<" to "<<hnc.x<<","<<hnc.y<<endl;
										MoveWirePartHead(wpnum, hc, hnc);
									}
									else if(b.type == PFOOT){
										int pnum = BFindPartNumWithFootNum(b.num);
										Part p = parts[pnum];
										if(debugmessages_on) cout<<"Moving part number "
												<<pnum<<" from "<<hc.x<<","
												<<hc.y<<" to "<<hnc.x<<","<<hnc.y<<endl;
										MovePart(pnum, hnc);
									}
									else if(b.type == WIREHEAD){
										int wnum = b.num;
										MoveWireHead(wnum, hc, hnc);
									}
									else{
										cout<<"ERROR: this shouldn't happen (id 3)"<<endl<<endl;
										return -1;
									}
								}
								if(debugmessages_on)
									cout<<"Moved a couple of WirePart heads and 1x1 Parts"<<endl;
								checkagain = true;
							}
							else if(debugmessages_on) cout<<"Couldn't get smaller distance"<<endl;
						}
						else if(debugmessages_on) cout<<"Could not find new place for them"<<endl;
					}
				}
			}
		}
		if(checkagain) didsomething = true;
	} while(checkagain);

	if(debugmessages_on) cout<<"Board::OptimizeConnectionPlaces(): Done."<<endl<<endl;

	if(didsomething) return 1;
	else return 0;
}

int Board::StraightenVertically()
{
	//Tarkistus, voiko wirepartseja tai johtoja vetää suoremmin pystysuunnassa
	//ja veto niin jos mahdollista
	/*cout<<"========================================================"<<endl
			<<"Checking if wireparts or wires can be straightened vertically"<<endl
			<<"========================================================"<<endl;*/
	cout<<"Board::StraightenVertically()"<<endl;
	bool checkagain, didsomething = false;
	do{
		if(debugmessages_on) cout<<"|||LOOP|||"<<endl;
		checkagain = false;
		/*if(debugmessages_on){
			cout<<"--------------------"<<endl;
			Draw();
			cout<<">>>>>>>>>>>>>>>>>"<<endl;
		}*/
		for(unsigned int y=0; y<height; y++){
			for(unsigned int x=0; x<width; x++){
				Contentblock block = Content(x,y);
				Coord thisheadc;
				thisheadc.x = x;
				thisheadc.y = y;
				Coord otherheadc;
				//onko tässä johto-osan jalka?
				if(block.type == WPFOOT){
					int wpnum = BFindWirePartNumWithFootNum(
							Content(thisheadc).num);
					otherheadc = wparts[wpnum].OtherHeadCoord(thisheadc);
					if(debugmessages_on) cout<<"Found wirepart foot number "
							<<block.num<<" in ("
							<<thisheadc.x<<","<<thisheadc.y<<")"<<endl;

					Coord newotherheadc = GetNearestHoleDirectlyConnectedToCoord(
							otherheadc, thisheadc.x, false);
					if(newotherheadc.exist){
						if(debugmessages_on) cout<<"Moving wirepart foot from "<<otherheadc.x<<","
								<<otherheadc.y<<" to "<<newotherheadc.x
								<<","<<newotherheadc.y<<endl;
						//siirretään johto-osan pää osoitteesta otherheadc
						//osoitteeseen newotherheadc
						MoveWirePartHead(wpnum, otherheadc, newotherheadc);
						checkagain = true;
						/*if(debugmessages_on){
							cout<<"--------------------"<<endl;
							Draw();
							cout<<">>>>>>>>>>>>>>>>>"<<endl;
						}*/
						continue;
					}
					
					Coord newthisheadc = GetNearestHoleDirectlyConnectedToCoord(
							thisheadc, otherheadc.x, false);
					if(newthisheadc.exist){
						if(debugmessages_on) cout<<"Moving wirepart foot from "<<thisheadc.x<<","
								<<thisheadc.y<<" to "<<newthisheadc.x
								<<","<<newthisheadc.y<<endl;
						//siirretään johto-osan pää osoitteesta thisheadc
						//osoitteeseen newthisheadc
						MoveWirePartHead(wpnum, thisheadc, newthisheadc);
						checkagain = true;
						/*if(debugmessages_on){
							cout<<"--------------------"<<endl;
							Draw();
							cout<<">>>>>>>>>>>>>>>>>"<<endl;
						}*/
						continue;
					}
				}
				//ei johto-osan jalkaa. onko johdon pää?
				else if(block.type == WIREHEAD){
					int wnum = BFindWireNumWithFootNum(block.num);
					if(wnum==-1){
						cout<<"Can't find wire number "<<wnum<<" from list"<<endl<<endl;
						return -1;
					}
					Wire w = wires[wnum];
					if(w.c1 == thisheadc) otherheadc = w.c2;
					else if(w.c2 == thisheadc) otherheadc = w.c1;
					else{
						cout<<"wrong wire head"<<endl<<endl;
						return -1;
					}

					if(debugmessages_on) cout<<"Found wire head number "
							<<block.num<<" in ("
							<<thisheadc.x<<","<<thisheadc.y<<")"<<endl;

					Coord newotherheadc = GetNearestHoleDirectlyConnectedToCoord(
							otherheadc, thisheadc.x, WIRE_ALLOW_BLOCKED);
					if(newotherheadc.exist){
						if(debugmessages_on) cout<<"Moving wire from "<<otherheadc.x<<","
								<<otherheadc.y<<" to "<<newotherheadc.x
								<<","<<newotherheadc.y<<endl;
						//siirretään johdon pää osoitteesta otherheadc osoitteeseen newotherheadc
						MoveWireHead(block.num, otherheadc, newotherheadc);
						checkagain = true;
						/*if(debugmessages_on){
							cout<<"--------------------"<<endl;
							Draw();
							cout<<">>>>>>>>>>>>>>>>>"<<endl;
						}*/
						continue;
					}
					
					Coord newthisheadc = GetNearestHoleDirectlyConnectedToCoord(
							thisheadc, otherheadc.x, WIRE_ALLOW_BLOCKED);
					if(newthisheadc.exist){
						if(debugmessages_on) cout<<"Moving wire from "<<thisheadc.x<<","
								<<thisheadc.y<<" to "<<newthisheadc.x
								<<","<<newthisheadc.y<<endl;
						//siirretään johdon pää osoitteesta thisheadc osoitteeseen newthisheadc
						MoveWireHead(block.num, thisheadc, newthisheadc);
						checkagain = true;
						/*if(debugmessages_on){
							cout<<"--------------------"<<endl;
							Draw();
							cout<<">>>>>>>>>>>>>>>>>"<<endl;
						}*/
						continue;
					}
				}
			}
		}
		if(checkagain) didsomething = true;
	} while(checkagain);
	
	if(debugmessages_on) cout<<"Board::StraightenVertically(): Done."<<endl<<endl;
	
	if(didsomething) return 1;
	else return 0;
}

int Board::CleanEverything(bool do_places, bool do_orders, bool do_straighten)
{
	if(!DISABLE_OPTIMIZATIONS){
		unsigned int loopcount = 0;
		bool checkagain;
		do{
			checkagain = false;
			int i;
			if(do_places){
				i = OptimizeConnectionPlaces();
				if(i==-1){
					cout<<"error: OptimizeConnectionPlaces failed"<<endl;
					return -1;
				}
				if(i==1) checkagain = true;
			}
			
			if(do_orders){
				i = OptimizeChunkOrders();
				if(i==-1){
					cout<<"ERROR: OptimizeChunkOrders failed"<<endl;
					return -1;
				}
				if(i==1) checkagain = true;
			}
			
			if(do_straighten){
				i = StraightenVertically();
				if(i==-1){
					cout<<"ERROR: StraightenVertically failed"<<endl;
					return -1;
				}
				if(i==1) checkagain = true;
			}
			loopcount++;
		} while(checkagain && loopcount <= CLEANEVERYTHING_LOOPCOUNT_MAX);
		if(loopcount>=2) return 1;
	}
	return 0;
}

int Board::RemoveUnnecessaryCuts()
{
	//otetaan ylimääräiset leikkaukset pois
	//HUOM: tämän pitää olla viimeinen kutsuttu funktio ennen generate():n
	//palautusta
	cout<<"=================================="<<endl
			<<"Removing unnecessary cuts"<<endl
			<<"=================================="<<endl;
	bool didsomething = false;
	for(unsigned int y=0; y<height; y++){

		//käydään läpi vasemmasta reunasta oikealle
		for(unsigned int x=0; x<width; x++){
			//Jos on leikattu, selataan eteen päin lisää seuraavasta ja muutetaan
			//seuraavaan jalkaan asti olevat leikkaukset reijiksi. Sen jälkeen
			//jatketaan tätä ulompaa luuppia siitä kohtaa josta jalka löytyi.
			if(contents[y][x].type==CUT){
				for(unsigned int x0=x+1; x0 < width; x0++){
					if(contents[y][x0].type==CUT){
						contents[y][x0].type = HOLE;
						didsomething = true;
					}
					else{
						x = x0;
						break;
					}
				}
			}
		}

		//Jos vasemmassa reunassa on leikkaus, muutetaan se reijäksi
		if(contents[y][0].type == CUT) contents[y][0].type = HOLE;

		//Muutetaan kaikki leikkaukset reijiksi oikeasta reunasta vasempaan
		//päin ensimmäiseen vastaantulevaan jalkaan asti
		for(unsigned int x=width-1; x>0; x--){
			if(contents[y][x].type == PFOOT || contents[y][x].type == WPFOOT) break;
			if(contents[y][x].type == CUT){
				contents[y][x].type = HOLE;
				didsomething = true;
				break;
			}
		}
	}
	if(didsomething) return 1;
	else return 0;
}

//////////////////////////////////////////////////////////////////////////////

//#define CHECKBLOCK_MODE_2

int Board::CheckBlock(unsigned int x, unsigned int y, unsigned int partxspacing, bool put_wires, bool put_wireparts, bool put_wireparts_to_random)
{
	Contentblock c = Content(x,y);
	Coord currentcoords;
	currentcoords.x = x;
	currentcoords.y = y;
	bool didsomething = false;
	//jos tässä on joku jalka
	if(c.type == PFOOT || c.type == WPFOOT){
		//kaivetaan jalka johon pitäisi olla yhteydessä
		vector<int> footnums_to_connect = circuitp->GetFootNumsConnected(c.num);
		for(unsigned int i=0; i<footnums_to_connect.size(); i++){
			int footnum_to_connect = footnums_to_connect[i];
			//löytyykö jalka, johon pitäisi olla yhteydessä, levyltä?
			Coord c_to_be_connected = FindFootNum(footnum_to_connect);
			if(c_to_be_connected.exist){
				Contentblock block_to_connect = Content(c_to_be_connected.x,
						c_to_be_connected.y);
				//löytyy
				//-> ollaanko yhteydessä?
				if(IsConnected(currentcoords, c_to_be_connected)){
					//ollaan, nou proplem
					continue;
				}
				//ei olla
				Coord otherfootcoords = FindFootNum(footnum_to_connect);
				if(!otherfootcoords.exist){
					//ei löytynyt jalkaa joka on levyllä :---o
					cout<<"wtf, foot is on board but its coordinates don't exist"<<endl;
					return -2;
				}
				else{
					if(debugmessages_on) cout<<"This block's ("<<currentcoords.x
							<<","<<currentcoords.y<<") foot number "<<c.num
							<<" should be connected to "
							<<footnum_to_connect<<" ("<<otherfootcoords.x<<","
							<<otherfootcoords.y<<") but it isn't"<<endl;
					bool connected = false;
					if(c.type==WPFOOT){
						if(debugmessages_on) cout<<"As this part seems to be a "
								"wirepart, trying to move our foot."<<endl;
						
						//jos wirepartin jalkaan ei ole yhdistettynä mitään,
						//liikutetaan sitä
						Coord footcoords = currentcoords;//FindFootNum(c.num);
						if(GetDirectlyConnectedCoord(footcoords).size() == 0){
							//siirrä tämä kiinni siihen jalkaan
							Coord footnewcoords =GetClosestPossibleHoleConnectedToCoord(
									footcoords, otherfootcoords, false);
							if(footcoords.exist && footnewcoords.exist){
								if(debugmessages_on) cout<<"Trying to move foot from "
										<<footcoords.x<<","<<footcoords.y<<" to "
										<<footnewcoords.x<<","<<footnewcoords.y<<endl;
								int wpartnum_this = BFindWirePartNumWithFootNum(c.num);
								if(LameMoveWirePartHead(wpartnum_this, footcoords,
										footnewcoords)){
									if(debugmessages_on) cout<<"WirePart's foot moved"
											<<endl;
									connected = true;
								}
							}
							else{
								if(debugmessages_on) cout<<"could not find hole to "
										"move to"<<endl;
								return -1;
							}
						}
						else{
							if(debugmessages_on)
								cout<<"Something already connected to foot ->"
										" not moving it"<<endl;
							//return -1; //wut?
						}
					}

					//jos toinen on johtotyyppinen ja edellisessä ei tehty mitään
					if(block_to_connect.type==WPFOOT && !connected){
						if(debugmessages_on) cout<<"The other part seems to be "
								"a wirepart, moving its foot."<<endl;
						//toinen on, joten siirrä sen jalka kiinni tähän jalkaan
						Coord footnewcoords =GetClosestPossibleHoleConnectedToCoord(
								otherfootcoords, currentcoords, false);
						if(footnewcoords.exist){
							if(debugmessages_on) cout<<"Trying to move foot from "
									<<otherfootcoords.x<<","<<otherfootcoords.y<<
									" to "
									<<footnewcoords.x<<","<<footnewcoords.y<<endl;
							int wpartnum_other =
									BFindWirePartNumWithFootNum(footnum_to_connect);
							//jos wirepartin jalkaan ei ole yhdistettynä mitään,
							//liikutetaan sitä
							if(GetDirectlyConnectedCoord(otherfootcoords).size()
									== 0){
								if(LameMoveWirePartHead(wpartnum_other, otherfootcoords, footnewcoords)){
									if(debugmessages_on) cout<<"WirePart's foot moved"<<endl;
									connected = true;
								}
							}
							else{
								if(debugmessages_on)
									cout<<"Something already connected to foot ->"
											" not moving it"<<endl;
								//return -1; //wut?
							}
						}
						else{
							if(debugmessages_on) cout<<"could not find hole to move to"<<endl;
							return -1;
						}
					}
					//jos edellisissä ei saatu tehtyä mitään
					if(!connected){
						//lisätään johto tai suora yhteys
						if(debugmessages_on) cout<<"trying to connect "
								<<currentcoords.x<<","<<currentcoords.y<<
								" and "<<otherfootcoords.x<<","<<otherfootcoords.y
								<<" directly or with wire"<<endl;
						if(!put_wires){
							cout<<"Not yet allowed to put wire"<<endl;
							continue;
						}
						if(ConnectCoord(currentcoords, otherfootcoords)){
							if(debugmessages_on) cout<<"connecting succeed"<<endl;
							connected = true;
						}
						else{
							if(debugmessages_on) cout<<"*** Connecting blocks failed"<<endl;
							return -1;
						}
					}
					//jos saatiin jotain yhdistettyä, varmistetaan xy:n
					//uudelleenplaraus tämän kierroksen jälkeen
					//if(connected) return 1;
					didsomething = true;
					continue;
				}
			}
			else{
				cout<<"Foot number "<<c.num<<" ("<<currentcoords.x
						<<","<<currentcoords.y<<") should be connected to foot num "
						<<footnum_to_connect<<" but it's not on board"<<endl;
				//levyllä oleva jalka, johon pitäisi olla yhteydessä, ei löydy 
				//-> pitäisi varmaankin tökätä jalan omistava komponentti jonnekin.
				//etsitään komponentti jolla olisi kyseinen jalka
				int partnum_to_add = circuitp->FindPartNumWithFootNum(footnum_to_connect);
				int wpartnum_to_add =circuitp->FindWirePartNumWithFootNum(footnum_to_connect);
				if(partnum_to_add != -1){
					if(debugmessages_on) cout<<"A normal part has the foot"<<endl;
					//löytyi haluttu osa
					Part newpart = circuitp->Parts()[partnum_to_add];
					cout<<"Adding Part "<<newpart.Name()<<"..."<<endl;
					//jos se on 1x1-kokoinen
					if(newpart.GetFootprint()->Width()==1 && newpart.GetFootprint()->Height()==1){
						cout<<"One-point part"<<endl;
						Coord partcoords = GetHoleConnectedToCoord(currentcoords,
								false);
						if(partcoords.exist){
							newpart.SetCoord(partcoords);
							if(PutPart(newpart)){
								if(debugmessages_on) cout<<"Added."<<endl;
								//return 1;
								didsomething = true;
								continue;
							}
						}
						else{
							cout<<"Could not find free hole"<<endl;
							return -1;
						}
					}
					//jos se on yli 1x1-kokoinen
					else{
						cout<<"Normal part"<<endl;
						if(PutPartToBestScoredPlace(newpart)){
							if(debugmessages_on) cout<<"Added"<<endl;
							didsomething = true;
							continue;
							//return 1;
						}
						else{
							if(debugmessages_on) cout<<"Failed to add part "
									<<newpart.Name()<<endl;
							return -1;
						}
					}
				}
				else if(wpartnum_to_add != -1){
					if(debugmessages_on) cout<<"A wirepart has the foot"<<endl;
					if(!put_wireparts){
						cout<<"Not yet allowed to put wireparts"<<endl;
						continue;
					}
					//löytyi haluttu johtotyyppinen osa
					//lisätään siis se
					WirePart wpart = circuitp->WireParts()[wpartnum_to_add];
					cout<<"Adding WirePart "<<wpart.Name()
							<<" connected to "<<currentcoords.x<<","<<currentcoords.y
							<<". foot1="<<wpart.FootNum1()<<" foot2="<<wpart.FootNum2()
							<<endl;

					//yhdistetään myös toinen pää jos se pitää yhdistää johonkin jo
					//levyllä olevaan
					Coord otherendcoords;
					otherendcoords.exist = false;

					//keksitään kumpi jalka on toinen
					int otherfootnum;
					bool footnum1_to_current;
					if(footnum_to_connect == wpart.FootNum1()){
						otherfootnum = wpart.FootNum2();
						footnum1_to_current = true;
						if(debugmessages_on) cout<<"Connecting footnum1 to this block"
								<<endl;
					}
					else if(footnum_to_connect == wpart.FootNum2()){
						otherfootnum = wpart.FootNum1();
						footnum1_to_current = false;
						if(debugmessages_on) cout<<"Connecting footnum2 to this block"
								<<endl;
					}
					else{
						cout<<"FATAL: footnum on board not on board"<<endl;
						return -2;
					}
					/*
					vector<Coord> coords_to_connect_otherhead;
					vector<int> footnums_to_connect_otherhead =
							circuitp->GetFootNumsConnected(otherfootnum);
					for(unsigned int i = 0; i<footnums_to_connect_otherhead.size(); i++){
						Coord coord_to_connect = FindFootNum(footnums_to_connect_otherhead[i]);
						if(coord_to_connect.exist){
							coords_to_connect_otherhead.push_back(coord_to_connect);
						}
					}
					
					bool put_somewhere = false;
					if(coords_to_connect_otherhead.empty()){
						if(debugmessages_on) cout<<"coords_to_connect_otherhead.empty() -> ";
						if(put_wireparts_to_random) {
							if(debugmessages_on) cout<<"put_somewhere = true;"<<endl;
							put_somewhere = true;
						}
						else{
							if(debugmessages_on) cout<<"continue;"<<endl;
							continue;
						}
					}
					
					vector<Coord> coords_connected_to_thishead = GetConnectedCoord(currentcoords);
					int ret = GetBestPlaceForWireThing(
					vector<int> coordnums_sorted_this, coordnums_sorted_other;
					for(unsigned int i=0; i<coords_connected_to_thishead.size(); i++){
						for(unsigned int j=0; j<coords_to_connect_otherhead.size(); j++){
							
					}


					*/


					Coord coords_to_connect;
					vector<int> footnums_to_connect_otherhead =
							circuitp->GetFootNumsConnected(otherfootnum);
					for(unsigned int i = 0; i<footnums_to_connect_otherhead.size(); i++){
						coords_to_connect = FindFootNum(footnums_to_connect_otherhead[i]);
						if(coords_to_connect.exist){
							//if(debugmessages_on) cout<<"Found coords ("
									//<<coords_to_connect.x<<","<<coords_to_connect.y
									//<<") for footnum to connect"<<endl;
							otherendcoords = GetClosestPossibleHoleConnectedToCoord(
									currentcoords, coords_to_connect, false);
							//löytyi ok jalka johon voidaan hakea yhdistävä paikka
							if(otherendcoords.exist) break;
							else{
								if(debugmessages_on)
									cout<<"Could not get free hole connected"
											<<"to "<<coords_to_connect.x<<","
											<<coords_to_connect.y<<endl;
							}
						}
						else if(debugmessages_on) cout<<"Footnum "
								<<footnums_to_connect_otherhead[i]
								<<" to connect not on board"<<endl;
					}
					if(footnums_to_connect_otherhead.size()==0)
						if(debugmessages_on)
								cout<<"WUT: The other head doesn't need"
										" to be connected anywhere"<<endl;

					if(!otherendcoords.exist){
						if(debugmessages_on) cout<<"Could not find place to connect the "
								"other head"<<endl;
						if(put_wireparts_to_random){
							if(debugmessages_on) cout<<"Putting just somewhere"<<endl;
							//TODO: kun nfc:t laitetaan jaloille, tuonne voidaan laittaa partxspacing+1:n tilalle partxspacing+nfc_count tms
							otherendcoords = FindClosestPossibleFreePlace(
									//currentcoords, 1, 1, partxspacing+1);
									currentcoords, 1, 1, 1);
							//otherendcoords = FindFreePlace(1, 1, partxspacing);
							//otherendcoords = FindFreePlace(4, 1, 0);
							//otherendcoords.x++;
							//otherendcoords = FindFreePlaceWithMaxRoom(1, 1);
							if(!otherendcoords.exist){
								if(debugmessages_on) cout<<"Could not find enough free space"
										"anywhere either"<<endl;
							}
						}
						else{
							if(debugmessages_on)
									cout<<"And not allowed to put just somewhere"
									" -> cancelling"<<endl;
							continue;
						}
					}
					/*else if(debugmessages_on) cout<<"Found coords ("<<otherendcoords.x<<","<<otherendcoords.y<<") for a hole to connect to"<<endl;*/
					if(otherendcoords.exist){
						bool this_foot_is_second = false;
						cout<<"otherendcoords = "<<otherendcoords.String()<<endl;
						if(otherfootnum == wpart.FootNum2()){
							wpart.SetCoord(MakeInexistentCoord(), otherendcoords);
						}
						else if(otherfootnum == wpart.FootNum1()){
							this_foot_is_second = true;
							wpart.SetCoord(otherendcoords, MakeInexistentCoord());
						}
						else{ cout<<"Fatal error"<<endl; return -2; }
						if(PutWirePartWisely(wpart, partxspacing) == false){
							cout<<"Error putting (half-defined) WirePart"<<endl;
							return -1;
						}
						else{
							int num = BFindWirePartNumWithFootNum(wpart.FootNum1());
							Coord thisendcoord = GetClosestPossibleHoleConnectedToCoord(otherendcoords, currentcoords, false);
							cout<<"thisendcoord="<<thisendcoord.String()<<endl;
							
							if(!thisendcoord.exist){
								if(debugmessages_on) cout<<"Could not get free hole connected to "<<currentcoords.x<<","<<currentcoords.y<<endl;
								cout<<"->removing wpart"<<endl;
								wparts.erase(wparts.begin()+num);
								return -1;
							}
							else{
								cout<<"wparts[num].C1()="<<wparts[num].C1().String()<<", wparts[num].C2()="<<wparts[num].C2().String()<<endl;
								if(!wparts[num].C1().exist){
									wparts[num].SetCoord(thisendcoord, wparts[num].C2());
									InformContentChanged();
									cout<<"WirePart succesfully (hopefully) put: "<<wparts[num].C1().String()<<"->"<<wparts[num].C2().String()<<endl;
									didsomething = true;
									continue;
									//return 1;

								}
								else if(!wparts[num].C2().exist){
									wparts[num].SetCoord(wparts[num].C1(), thisendcoord);
									InformContentChanged();
									cout<<"WirePart succesfully (hopefully) put: "<<wparts[num].C1().String()<<"->"<<wparts[num].C2().String()<<endl;
									//return 1;
									didsomething = true;
									continue;
								}
								else{
									cout<<"VIRHHHE!"<<endl;
									return -2;
								}
							}
						}
					}
					else{
						if(debugmessages_on) cout<<"Could not find good place"<<endl;
						return -1;
					}
				}
				else{
					cout<<"Error: Foot number "<<c.num<<" is connected to foot number "
							<<footnum_to_connect<<" but no part has that foot"<<endl;
					return -2;
				}
			}
		}
	}

	if(didsomething) return 1;
	else return 0;
}

#define MODE_1
//#define MODE_2 //ihan baskan random
//#define CROP
//#define CUT_STARTS
//#define CUT_ENDS
#define REMOVE_UNNECESSARY_CUTS

bool Board::Generate(Circuit *circuitp_, unsigned int width_, unsigned int height_)
{
	cout<<"Board::Generate() (debugmessages "<<(debugmessages_on?"on":"off")<<")"<<endl;
	/*if(maxw==0){
		cout<<"error: maxw=0"<<endl;
		return false;
	}*/

	unsigned int partxspacing = 2;
	bool fits;
	//unsigned int wantedwidth;
	//bool width_went_over = false;

	additional_x_spacing = 0;

	circuitp = circuitp_;
	
	//vector<Part> circuitparts = circuit.Parts();
	/*for(unsigned int i=0; i<circuitparts.size(); i++){
		cout<<circuitparts[i].Name()<<", ("<<circuitparts[i].GetCoord().x<<","<<circuitparts[i].GetCoord().y<<") "<<circuitparts[i].GetFootprint()->Width()<<endl;
	}*/
	//circuitparts = SortPartsByFootCount(circuitparts);
	/*for(unsigned int i=0; i<circuitparts.size(); i++){
		cout<<circuitparts[i].Name()<<", ("<<circuitparts[i].GetCoord().x<<","<<circuitparts[i].GetCoord().y<<") "<<circuitparts[i].GetFootprint()->Width()<<endl;
	}*/
	//vector<WirePart> circuitwparts = circuit.WireParts();
	//vector<Connection> cons = circuit.Connections();
	
	/*if(maxw>CMAXW) maxw = CMAXW;
	wantedwidth = maxw;*/
	
	if(circuitp->Parts().size()==0){
		cout<<"Board::Generate needs at least one part"<<endl;
		return false;
	}

clear_and_generate:
	//cout<<"============ Clear And Generate ============"<<endl;
	width = width_;
	height = height_;
	if(width >CMAXW) width  = CMAXW;
	if(height>CMAXH) height = CMAXH;
#if 0
#ifdef MODE_1
	width = wantedwidth;
	height = wantedwidth*2;//CMAXH;
	if(height > CMAXH) height = CMAXH;
#endif
#ifdef MODE_2
	/*width = CMAXW;
	height = CMAXH;*/
	width = wantedwidth;
	height = wantedwidth;
#endif
#endif
	cout<<"- Trying with additional_x_spacing="<<additional_x_spacing<<" width="<<width<<" height="<<height<<endl;
	fits = true;
	
	/*
	//cout<<"- Emptying board"<<endl;
	//tyhjätään levy
	Contentblock emptyblock;
	for(unsigned int y=0; y<CMAXH; y++){
		for(unsigned int x=0; x<CMAXW; x++){
			contents[y][x] = emptyblock;
		}
	}
	*/
	//tyhjätään osat ja johdot
	parts.clear();
	wparts.clear();
	wires.clear();
	dconns.clear();
	//footnums_as_nfc.clear();
	InformContentChanged();

	//nollataan numcountterit
	wirenumcounter = 0;
	dconnnumcounter = 0;
	
	//lisätään kiinteäjalkai(set/nen) osa(t)
	
	bool added_some_static_parts = false;
	vector<Part> cparts = circuitp->Parts();
	for(unsigned int i=0; i<cparts.size(); i++){
		Coord c = cparts[i].GetCoord();
		if(debugmessages_on) cout<<"Checking coord existance: \""<<cparts[i].Name()<<"\""<<endl;
		if(c.exist){
			//if(IsFreePlaceForPart(cparts[i], c.x, c.y)){
				cout<<"Adding static part named \""<<cparts[i].Name()<<"\""<<endl;
				if(PutPart(cparts[i]) == false){
					cout<<"First part doesn't fit"<<endl;
					return false;
				}
				added_some_static_parts = true;
			/*}
			else{
				cout<<"Invalid static place for part named \""<<cparts[i].Name()<<"\""<<endl;
				//fits = false;
				return false;
			}*/
		}
		else if(debugmessages_on) cout<<"!exist"<<endl;
	}
	if(!added_some_static_parts){
		//lisätään kiinteäjalkai(set/nen) osa(t)
		
		cout<<"- Adding first part"<<endl;

#ifdef MODE_1
		if(!PutPartSomewhere(cparts[0])){
		//if(!PutPartSomewhereWithMaxRoom(circuit.Parts()[0])){
			cout<<"* Could not add first part (MODE_1)"<<endl;
			fits = false;
		}
#endif
		/*cout<<"- Adding parts"<<endl;
		for(unsigned int i=0; i<circuit.Parts().size(); i++){
			if(!PutPartSomewhere(circuit.Parts()[i])){
				cout<<"Could not add part"<<endl;
				fits = false;
				break;
			}
		}*/

#ifdef MODE_2
		Part p = cparts()[0];
		Coord c;
		c.x = width/2 - p.GetFootprint()->Width()/2;
		c.y = height/2 - p.GetFootprint()->Height()/2;
		p.SetCoord(c);
		if(!PutPart(p)){
			cout<<"* Could not add first part (MODE_2)"<<endl;
			fits = false;
		}
#endif
	}

	//bool aaa = false; //DEBUG
	
	/*bool put_wires = false;
	bool put_wireparts = false;*/
	bool put_wires = true;
	bool put_wireparts = true;
	//bool put_wireparts_to_random = false;
	bool put_wireparts_to_random = true;
	unsigned int phasecounter = 0;
	bool error;
	bool checkagain;
//bbb:
	if(fits){
	cout<<"========================================================"<<endl
			<<"Checking connections and adding components"<<endl
			<<"========================================================"<<endl;
	do{
		checkagain = false;
		error = false;
		//cout<<"- Phase "<<phasecounter<<endl;

		//for(int y=height-1; y>=0; y--){
			//for(int x=width-1; x>0; x--){
		for(unsigned int y=0; y<height; y++){
			for(unsigned int x=0; x<width; x++){
				int ret = CheckBlock(x, y, partxspacing, put_wires, put_wireparts, put_wireparts_to_random);
				switch(ret){
				case -2:
					cout<<"returned -2"<<endl;
					return false;
					break;
				case -1:
					cout<<"returned -1"<<endl;
					error = true;
					goto cancel;
					break;
				case 0:
					//cout<<"returned 0"<<endl;
					//ei tehty mitään
					break;
				case 1:
					cout<<"returned 1"<<endl;
					checkagain = true;
					break;
				default:
					cout<<"returned "<<ret<<endl;
					return false;
				}
			}
		}
		if(put_wires || put_wireparts){
			if(CleanEverything(1,1,DO_STRAIGHTEN_EVERY_TIME) == -1){
				cout<<"CleanEverything failed"<<endl;
				return false;
			}
		}
		if(!checkagain){
			//cout<<"- No check requested anymore"<<endl;
			//ei enää tehtävää -> aletaan laittaa johto-osia randomimmasti jos ei vielä laiteta
			if(!put_wires){
				if(debugmessages_on) cout<<"- Allowing to put wires"<<endl;
				put_wires = true;
				checkagain = true;
			}
			else if(!put_wireparts){
				if(debugmessages_on) cout<<"- Allowing to put wireparts"<<endl;
				put_wireparts = true;
				checkagain = true;
			}
			else if(!put_wireparts_to_random){
				if(debugmessages_on) cout<<"- Allowing to put wireparts randomly"<<endl;
				put_wireparts_to_random = true;
				checkagain = true;
			}
			//muuten poistutaan loopista (!checkagain)
		}
		phasecounter++;
	} while(checkagain);
	}

cancel:

	//jos tuli errori
	if(error){
		cout<<"* Failed to complete"<<endl;
		if(additional_x_spacing < MAX_ADDITIONAL_X_SPACING){
		//if(0){
			additional_x_spacing++;
			cout<<"- Changing additional_x_spacing to "<<additional_x_spacing
					<<" and trying again"<<endl;
			goto clear_and_generate;
		}
		else{
			cout<<"- Not changing additional_x_spacing (="<<additional_x_spacing<<")"<<endl;
			cout<<"* An uncorrectable error"<<endl;
			//return false;
			fits = false;
		}
	}
	else{
		if(CleanEverything(1,1,1) == -1){
			cout<<"CleanEverything failed"<<endl;
			return false;
		}
	}

#ifdef CROP
	if(fits && !error){
		cout<<"Cropping"<<endl;
		unsigned int xoffset=0, yoffset=0;
#ifdef CUT_STARTS
		//tutkitaan paljonko tyhjää on ylhäällä
		for(unsigned int y=0; y<height; y++){
			bool somethingfound = false;
			for(unsigned int x=0; x<width; x++){
				if(Content(x, y).type!=CUT){
					somethingfound = true;
					break;
				}
			}
			if(somethingfound){
				yoffset = y;
				break;
			}
		}
		//tutkitaan paljonko tyhjää on vasemmalla
		for(unsigned int x=0; x<width; x++){
			bool somethingfound = false;
			for(unsigned int y=0; y<height; y++){
				if(Content(x, y).type!=CUT){
					somethingfound = true;
					break;
				}
			}
			if(somethingfound){
				xoffset = x;
				break;
			}
		}
#endif
		
		cout<<"xoffset="<<xoffset<<" yoffset="<<yoffset<<endl;

		//vaihdetaan kaikkien osien koordinaatit
		for(unsigned int i=0; i<parts.size(); i++){
			Coord c = parts[i].GetCoord();
			c.x -= xoffset;
			c.y -= yoffset;
			parts[i].SetCoord(c);
		}
		//vaihdetaan kaikkien johto-osien koordinaatit
		for(unsigned int i=0; i<wparts.size(); i++){
			Coord c1 = wparts[i].C1();
			Coord c2 = wparts[i].C2();
			c1.x -= xoffset;
			c1.y -= yoffset;
			c2.x -= xoffset;
			c2.y -= yoffset;
			wparts[i].SetCoord(c1, c2);
		}
		//vaihdetaan kaikkien johtojen koordinaatit
		for(unsigned int i=0; i<wires.size(); i++){
			Coord c1 = wires[i].C1();
			Coord c2 = wires[i].C2();
			c1.x -= xoffset;
			c1.y -= yoffset;
			c2.x -= xoffset;
			c2.y -= yoffset;
			wires[i].SetCoord(c1, c2);
		}
		//#if 0
		//siirretään juttuja taulukossa
		for(unsigned int y=0; y+yoffset<height; y++){
			for(unsigned int x=0; x+xoffset<width; x++){
				unsigned int blockx = x+xoffset;
				unsigned int blocky = y+yoffset;
				Contentblock b = Content(blockx, blocky);
				if(b.type == PFOOT || b.type == WPFOOT || b.type == CUT || b.type == HOLE){
					contents[y][x] = b;
				}
				else if(b.type == WIREHEAD){
					contents[y][x] = b;
					//int i = GetWireNumByNum(b.num);
					int i = b.num;
					if(wires[i].c1.x == blockx && wires[i].c1.y == blocky){
						//tämä on ykköspää, muutetaan sen koordinaatit
						wires[i].c1 = MakeCoord(x, y);
					}
					else{
						//tämä on kakkospää, muutetaan sen koordinaatit
						wires[i].c2 = MakeCoord(x, y);
					}
				}
				/*else if(b.type == CUT || b.type == HOLE){
					contents[y][x] = b;
				}*/
				else{
					cout<<"* invalid content (="<<b.type<<") on "<<blockx<<","<<blocky<<endl;
					return false;
				}
			}
		}
		//tyhjätään loppu levystä
		Contentblock emptyblock;
		for(unsigned int y = height - yoffset; y < height; y++){
			for(unsigned int x=0; x < width; x++){
				contents[y][x] = emptyblock;
			}
		}
		for(unsigned int x = width - xoffset; x < width; x++){
			for(unsigned int y=0; y < height-yoffset; y++){
				contents[y][x] = emptyblock;
			}
		}
		//#endif

#ifdef CUT_ENDS
		//otetaan turhat alhaalta pois
		for(unsigned int y=height-1; y>0; y--){
			bool somethingfound = false;
			for(unsigned int x=0; x<width; x++){
				if(Content(x, y).type!=CUT && Content(x, y).type!=HOLE){
					somethingfound = true;
					break;
				}
			}
			if(somethingfound){
				height = y+1;
				break;
			}
		}
		//otetaan turhat oikealta pois
		for(unsigned int x=width-1; x>0; x--){
			bool somethingfound = false;
			for(unsigned int y=0; y<height; y++){
				if(Content(x, y).type!=CUT && Content(x, y).type!=HOLE){
					somethingfound = true;
					break;
				}
			}
			if(somethingfound){
				width = x+1;
				break;
			}
		}
#endif
		cout<<"- Now width="<<width<<" height="<<height<<endl;
	}
#endif

#ifdef REMOVE_UNNECESSARY_CUTS
	cout<<"Removing unnecessary cuts"<<endl;
	//otetaan ylimääräiset leikkaukset pois
	for(unsigned int y=0; y<height && width!=0; y++){
		for(unsigned int x=0; x<width; x++){
			if(Content(x,y).type==CUT){
				for(unsigned int x0=x+1; x0 < width; x0++){
					if(Content(x0,y).type==CUT) contents[y][x0].type = HOLE;
					else{
						x = x0;
						break;
					}
				}
			}
		}
		if(Content(0,y).type == CUT) contents[y][0].type = HOLE;
		for(unsigned int x=width-1; x>0; x--){
			if(Content(x,y).type == PFOOT || Content(x,y).type == WPFOOT) break;
			if(Content(x,y).type == CUT){
				contents[y][x].type = HOLE;
				break;
			}
		}
	}
#endif

	//if(debugmessages_on){
		cout<<"-------------------------------------------------------------------------------"<<endl;
		Draw();
		cout<<"-------------------------------------------------------------------------------"<<endl;
	//}
	
	if(fits){
		valid = true;
		return true;
	}
	else{
		valid = false;
		return false;
	}
}

//////////////////////////////////////////////////////////////////////////////

bool Board::UpdateContent(void)
{
	//cout<<"Board::UpdateContent()"<<endl;
	//cout<<"Board::UpdateContent(): Emptying board"<<endl;
	//tyhjätään levy
	Contentblock emptyblock;
	for(unsigned int y=0; y<CMAXH; y++){
		for(unsigned int x=0; x<CMAXW; x++){
			contents[y][x] = emptyblock;
		}
	}
	//cout<<"Board::UpdateContent(): WireParts"<<endl;
	for(unsigned int i=0; i<wparts.size(); i++){
		WirePart wp = wparts[i];
		unsigned int x1 = wp.C1().x;
		unsigned int y1 = wp.C1().y;
		unsigned int x2 = wp.C2().x;
		unsigned int y2 = wp.C2().y;
		if(wp.C1().exist && wp.C2().exist){
			if((Content(x1,y1).type == HOLE || Content(x1,y1).type == CUT) &&
					(Content(x2,y2).type == HOLE || Content(x2,y2).type == CUT)){
				contents[y1][x1].type = WPFOOT;
				contents[y1][x1].num = wp.FootNum1();
				contents[y2][x2].type = WPFOOT;
				contents[y2][x2].num = wp.FootNum2();
			}
			else{
				cout<<"Board::UpdateContent: ERROR: wirepart in wrong place: name=\""<<wp.Name()<<"\" c1="<<wp.C1().String()<<", c2="<<wp.C2().String()<<endl;
				return false;
			}
		}
		else if(wp.C1().exist){
			if(Content(x1,y1).type == HOLE || Content(x1,y1).type == CUT){
				contents[y1][x1].type = WPFOOT;
				contents[y1][x1].num = wp.FootNum1();
			}
			else{
				cout<<"Board::UpdateContent: ERROR: wirepart in wrong place: name=\""<<wp.Name()<<"\" c1="<<wp.C1().String()<<", c2="<<wp.C2().String()<<endl;
				return false;
			}
		}
		else if(wp.C2().exist){
			if(Content(x2,y2).type == HOLE || Content(x2,y2).type == CUT){
				contents[y2][x2].type = WPFOOT;
				contents[y2][x2].num = wp.FootNum2();
			}
			else{
				cout<<"Board::UpdateContent: ERROR: wirepart in wrong place: name=\""<<wp.Name()<<"\" c1="<<wp.C1().String()<<", c2="<<wp.C2().String()<<endl;
				return false;
			}
		}
		else{
			cout<<"Board::UpdateContent(): erroneus WirePart: name=\""<<wp.Name()<<"\" c1="<<wp.C1().String()<<", c2="<<wp.C2().String()<<endl;
		}
	}
	//cout<<"Board::UpdateContent(): Parts"<<endl;
	for(unsigned int i=0; i<parts.size(); i++){
		//cout<<"Board::UpdateContent(): Part "<<i<<endl;
		Part part = parts[i];
		if(!part.GetCoord().exist){
			cout<<"Board::UpdateContent (part): coords inexistent"<<endl;
			return false;
		}
		if(circuitp == NULL){
			cout<<"Board::UpdateContent (part): ERROR: circuitp NULL"<<endl;
			return false;
		}
		unsigned int x = part.GetCoord().x;
		unsigned int y = part.GetCoord().y;
		vector< vector<Contentblock> > cblocks = part.GetFootprint()->Contentblocks();
		unsigned int h = cblocks.size();
		unsigned int w = cblocks[0].size();
		//cout<<"Board:UpdateContent (part): w="<<w<<" h="<<h<<endl
		if(Width() > x+w-1 && Height() > y+h-1){
			for(unsigned int y0=0; y0<h; y0++){
				for(unsigned int x0=0; x0<w; x0++){
					//cout<<"cblocks["<<y0<<"]["<<x0<<"].type == "<<cblocks[y0][x0].type<<endl;
					contents[y+y0][x+x0] = cblocks[y0][x0];
					if(contents[y+y0][x+x0].partname_blocks == "this"){
						contents[y+y0][x+x0].partname_blocks = part.Name();
					}
				}
			}
			/*//jos kyseessä on 1x1-kokoinen osa, ei välitetä nfc:istä
			if(w==1 && h==1){
				parts.push_back(part);
				return true;
			}*/
			//lisäillään NFC:t
			for(unsigned int y1=0; y1<h; y1++){
				int nfcleft  = GetPartNFCleft(part, y1);
				if(nfcleft == -1){
					cout<<"Board::UpdateContent (part): ERROR: nfcleft==-1"<<endl;
					return false;
				}
				int nfcright = GetPartNFCright(part, y1);
				if(nfcright == -1){
					cout<<"Board::UpdateContent (part): ERROR: nfcright==-1"<<endl;
					return false;
				}
				int y2 = y + y1;
				//cout<<"nfcleft = "<<nfcleft<<" (y2="<<y2<<")"<<endl;
				for(int x1 = 0; x1 < nfcleft; x1++){
					int x2 = x-x1-1;
					if(x2 < 0) continue;
					//cout<<"("<<x2<<","<<y2<<")"<<endl;
					contents[y2][x2].nfc_partnum = i;
				}
				//cout<<"nfcright = "<<nfcright<<endl;
				for(int x1 = 0; x1 < nfcright; x1++){
					int x2 = x+x1+w;
					if(x2 >= (int)width) continue;
					//cout<<"("<<x2<<","<<y2<<")"<<endl;
					contents[y2][x2].nfc_partnum = i;
				}
			}
		}
		else{
			cout<<"Board::UpdateContent (part): Can't put here"<<endl;
			return false;
		}
	}
	//cout<<"Board::UpdateContent(): Wires"<<endl;
	for(unsigned int i=0; i<wires.size(); i++){
		Wire wire = wires[i];
		//TODO: pitäisiköhän tarkistaa koordinaattien järkevyys
		contents[wire.c1.y][wire.c1.x].type = WIREHEAD;
		contents[wire.c1.y][wire.c1.x].num = wire.num;
		contents[wire.c2.y][wire.c2.x].type = WIREHEAD;
		contents[wire.c2.y][wire.c2.x].num = wire.num;
	}
	//cout<<"Board::UpdateContent(): DConns"<<endl;
	for(unsigned int i=0; i<dconns.size(); i++){
		DConn dc = dconns[i];
		vector<Coord> nodes;
		dc.GetNodes(nodes);
		for(unsigned int j=0; j<nodes.size(); j++){
			if(Content(nodes[j].x, nodes[j].y).type == CUT)
				contents[nodes[j].y][nodes[j].x].type = HOLE;
		}
	}
	//if(debugmessages_on) cout<<"Board::UpdateContent(): Done."<<endl;
	return true;
}

void Board::InformContentChanged(void)
{
	//päivitetään vaan heti eikä jahkailla mitään (vaikka voisi ehkä)
	//TODO: miten olisi virheentarkistus? (palauttaa false jos evotti)
	UpdateContent();
	if(debugmessages_on){
		cout<<"------------------------InformContentChanged()---------------------------------"<<endl;
		Draw();
		cout<<"-------------------------------------------------------------------------------"<<endl;
	}
}

Contentblock Board::Content(unsigned int x, unsigned int y)
{
	if(x<Width() && y<Height()){
		return contents[y][x];
	}
	Contentblock b;
	b.type = OVERBOARD;
	return b;
}

Contentblock Board::Content(Coord c)
{
	return Content(c.x, c.y);
}

bool Board::Valid()
{
	return valid;
}

unsigned int Board::Width()
{
	return width;
}

unsigned int Board::Height()
{
	return height;
}

vector<Wire> Board::GetWires()
{
	return wires;
}
vector<Part> Board::GetParts()
{
	return parts;
}
vector<WirePart> Board::GetWireParts()
{
	return wparts;
}

void Board::Draw()
{
	vector<Wire> wires = GetWires();
	vector<Part> parts = GetParts();
	vector<WirePart> wireparts = GetWireParts();
	for(unsigned int i=0; i<dconns.size(); i++){
		cout<<"DConn "<<dconns[i].num<<": "<<dconns[i].c1.x<<","<<dconns[i].c1.y<<" -> "
				<<dconns[i].c2.x<<","<<dconns[i].c2.y<<endl;
	}
	for(unsigned int i=0; i<wires.size(); i++){
		cout<<"Wire "<<wires[i].num<<": "<<wires[i].c1.x<<","<<wires[i].c1.y<<" -> "
				<<wires[i].c2.x<<","<<wires[i].c2.y<<endl;
	}
	for(unsigned int i=0; i<parts.size(); i++){
		cout<<"Part "<<parts[i].Name()<<": "<<parts[i].GetCoord().x<<","
				<<parts[i].GetCoord().y<<endl;
	}
	for(unsigned int i=0; i<wireparts.size(); i++){
		cout<<"WirePart "<<wireparts[i].Name()<<": "<<wireparts[i].C1().x<<","
				<<wireparts[i].C1().y<<" -> "<<wireparts[i].C2().x<<","
				<<wireparts[i].C2().y<<endl;
	}
	
	unsigned int realheight = Height();
	/*//lasketaan tarvittava näytettävä korkeus
	for(unsigned int y=height-1; y>0; y--){
		bool somethingfound = false;
		for(unsigned int x=0; x<width; x++){
			if(Content(x, y).type != CUT && Content(x, y).type != HOLE){
				somethingfound = true;
				break;
			}
		}
		if(somethingfound){
			realheight = y+1;
			break;
		}
	}*/

	cout<<"   ";
	for(unsigned int x=0; x<Width(); x+=2) printf("%.2i  ", x);
	cout<<endl<<"     ";
	for(unsigned int x=1; x<Width(); x+=2) printf("%.2i  ", x);
	cout<<endl;
	for(unsigned int y=0; y<realheight; y++){
		printf("%.2i ", y);
		string row;
		for(unsigned int x=0; x<Width(); x++){
			Contentblock c = Content(x,y);
			Contentblock n = Content(x+1, y);
			if(c.type==OVERBOARD) row+="B";
			else if(c.type==CUT) row+="X";
			else if(c.type==HOLE) row+=".";
			else if(c.type==PFOOT) row+="o";
			else if(c.type==WPFOOT) row+="o";
			else if(c.type==WIREHEAD){
				string s = itos(c.num);
				row += s;
				if(s.size()==2) continue;
			}
			else row+="E";
			if(n.partname_blocks != "" || c.partname_blocks != "") row+="T";
			//else */if(c.nfc_partnum>=0) row+=")";
			else row+=" ";
		}
		cout<<row<<endl;
	}
	/*//tulostetaan kääntöpuoli
	cout<<"   ";
	for(int x=Width()-1; x>=0; x-=2) printf("%.2i  ", x);
	cout<<endl<<"     ";
	for(int x=Width()-2; x>=0; x-=2) printf("%.2i  ", x);
	cout<<endl;
	for(unsigned int y=0; y<Height(); y++){
		printf("%.2i ", y);
		string row;
		for(int x=Width()-1; x>=0; x--){
			Contentblock c = Content(x,y);
			Contentblock n = Content(x+1, y);
			if(c.type==OVERBOARD) row+="B";
			else if(c.type==CUT) row+="X";
			else if(c.type==HOLE) row+=".";
			else if(c.type==FOOT) row+=".";
			else if(c.type==WIREHEAD) row+=".";
			else row+="E";
			//if(n.component_blocks || c.component_blocks) row+="T";
			//else row+=" ";
			row += " ";
		}
		cout<<row<<endl;
	}*/
	cout<<"(X = cut, . = hole, o = leg, <number> = wire, T=component in front)"<<endl;
}

